• Spring的注解问题


    Annotation(注解)概述

    从JDK5.0开始, Java增加了对元数据(MetaData)的支持,也就是 Annotation(注解)。 
    Annotation其实就是代码里的特殊标记,它用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行。在Java技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。 

    1.自定义一个注解:

    @Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
    	String temp() default "";
    }

    (1).@Retention– 定义该注解的生命周期
      RetentionPolicy.SOURCE : 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
      RetentionPolicy.CLASS : 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式
      RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。

    (2).@Target – 表示该注解用于什么地方。默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
      ElementType.CONSTRUCTOR:用于描述构造器
      ElementType.FIELD:成员变量、对象、属性(包括enum实例)
      ElementType.LOCAL_VARIABLE:用于描述局部变量
      ElementType.METHOD:用于描述方法
      ElementType.PACKAGE:用于描述包
      ElementType.PARAMETER:用于描述参数
      ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明

    2.Spring使用注解。

    在Spring核心配置文件配置:

    1 <context:component-scan base-package="cn.*"/> <!-- 扫描cn包下的所有Bean -->
    2 <context:component-scan base-package="cn.pojo,cn.test"/> <!-- 扫描指定包下的Bean,用逗号隔开 -->

    如果扫描到的类上带有特定的注解(以下注解),这个对象就会交给Spring容器管理。

    @Component:是所有受Spring容器管理的通用组件形式,可以放在类头上,并不推荐使用。

    1   @Component("userDao")//这里通过注解定义了一个DAO
    2   public class UserDaoImp implements IUserDao {
    3      @Override
    4     public int addUser(User user) {
    5      //这里并未实现数据库操作,仅作为说明问题
    6         System.out.println("新增用户操作");
    7           return 0;
    8       }
    9  }

    @Repository:用于标注DAO类。

    1 @Repository("userDao")
    2 public class UserDaoImp implements IUserDao {
    3     @Override
    4     public int addUser(User user) {
    5         System.out.println("新增用户操作");
    6         return 0;
    7     }
    8 }

    在数据访问层使用此标注userdao类,然后在业务逻辑层实现注解的注入。

    1     @Resource(name="userDao")
    2     
    3     @Autowired
    4     @Qualifier("userDao")
    5     private IUserDao userDao;

    JDK提供的注解:@Resource:根据name指定相应的dao类进行注入到userDao属性。

    Spring框架内部提供的注解:@Autowired:根据type进行自动装载,可配合@Qualifier注解根据name值进行注入。

      1.@Autowired也可以对方法进行入参进行注入:

    1     private IUserDao userDao;
    2     
    3     @Autowired
    4     public void setUserDao(@Qualifier("userDao")IUserDao userDao) {
    5         this.userDao = userDao;
    6     }

      2.使用@autowired注解进行装配时,如果找不到相匹配的Bean组件,Spring容器会抛出异常。如果依赖不是必须的,则可以将required的属性的设置为false。默认是为true的,即必须找到相匹配的Bean完成装配,否则就抛出一个异常。

    1     private IUserDao userDao;
    2     
    3     @Autowired(required = false)
    4     public void setUserDao(@Qualifier("userDao")IUserDao userDao) {
    5         this.userDao = userDao;
    6     }

       3.如果对类中集合类型的成员变量或方法入参使用@autowired注解,Spring会将容器中所有和集合中的元素类型进行匹配的Bean组件都注入进来。

    1      @Autowired(required = false)
    2      private List<User> list;//Spring容器会将User类型的Bean组件都注入给list属性。

    @Service:用于标注业务类。

     1  @Service("userService")
     2  public class UserServiceImp implements IUserService {
     3      @Resource(name="userDao")
     4     private IUserDao userDao;
     5      
     6      @Override
     7     public int addUser(User user) {
     8          return userDao.addUser(user);
     9       }
    10  }

    @Service("userService")注解是告诉Spring,当Spring要创建UserServiceImpl的实例时,bean的名字必须叫做“userService”,这样当Action需要使用UserServiceImpl的实例时,
    就可以由Spring创建好的“userService”然后注入给Action:在Action只需要声明一个名字叫“userService”的变量来接收由Spring注入的“userService”。

    @Controller:用来标注控制器类,也就是Action。


    使用注解定义切面
    AspectJ:是一个面向切面的框架,扩展了Java语言,定义了AOP语法,能够在编译期提供代码的织入,所有它拥有一个专门的编译器用来生成遵守字节编码的规范Class文件。
    @AspectJ是AspectJ 5新增的功能,使用JDK 5.0注解技术和正规的切点表达式语言描述切面。所以在使用之前,需要保证JDK版本是5.0以上版本,否则无法使用。

      1.使用注解标注切面

     1 package cn.advice;
     2 
     3 import org.apache.log4j.Logger;
     4 import org.aspectj.lang.JoinPoint;
     5 import org.aspectj.lang.ProceedingJoinPoint;
     6 import org.aspectj.lang.annotation.After;
     7 import org.aspectj.lang.annotation.AfterReturning;
     8 import org.aspectj.lang.annotation.AfterThrowing;
     9 import org.aspectj.lang.annotation.Around;
    10 import org.aspectj.lang.annotation.Aspect;
    11 import org.aspectj.lang.annotation.Before;
    12 import org.aspectj.lang.annotation.Pointcut;
    13 import org.springframework.stereotype.Component;
    14 
    15 @Component("serviceAdvice")
    16 @Aspect
    17 public class ServiceLoggingAdvice {
    18     private Logger logger = Logger.getLogger(ServiceLoggingAdvice.class);
    19     //定义切入点---可使用模糊查询进行匹配
    20     @Pointcut("execution(* cn.dao..*.*(..))")
    21     public void pointcut(){}
    22     //标注前置增强
    23     @Before(value = "pointcut()")
    24     public void before(JoinPoint joinPoint){
    25         String methodName = joinPoint.getSignature().getName();//获得目标方法名
    26         String className = joinPoint.getTarget().getClass().getSimpleName();//获得目标方法的类名
    27         logger.info("前置增强....");
    28         
    29     }
    30     //后置增强
    31     @AfterReturning(pointcut="pointcut()")
    32     public void after(JoinPoint joinPoint){
    33         logger.info("后置增强....");
    34     }
    35     //异常抛出增强
    36     @AfterThrowing(pointcut = "pointcut()",throwing = "e")
    37     public void afterThrowing(JoinPoint joinPoint,Exception e){
    38         String exeMessage = e.getMessage();
    39         logger.info(exeMessage);
    40     }
    41     //后置增强
    42     @After("pointcut()")
    43     public void afterEnd(JoinPoint joinPoint){
    44         logger.info("最终增强....");
    45     }
    46     //环绕增强
    47     @Around("execution(* cn.service..*.*(..))")
    48     public Object round(ProceedingJoinPoint joinPoint){
    49         Object result = null;
    50         try {
    51             logger.info("环绕增强 ------前面。。");
    52             
    53             result = joinPoint.proceed();//此方法调用真正的目标方法,从而实现对连接点的完全控制。
    54             
    55             logger.info("环绕增强 ------后面。。");
    56         } catch (Throwable e) {
    57             e.printStackTrace();
    58         }
    59         return result;
    60     }
    61 }

      2.在核心XML配置文件

        (1)首先导入aop命名空间

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     4     xmlns:p="http://www.springframework.org/schema/p"
     5     xmlns:aop="http://www.springframework.org/schema/aop" 
     6     xmlns:tx="http://www.springframework.org/schema/tx"
     7     xmlns:context="http://www.springframework.org/schema/context"
     8     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     9      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    10      http://www.springframework.org/schema/tx
    11      http://www.springframework.org/schema/tx/spring-tx.xsd
    12      http://www.springframework.org/schema/aop 
    13      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    14      http://www.springframework.org/schema/context
    15      http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    16 </beans>

        (2)在核心配置文件里加入<aop:aspectj-autoproxy />元素,就可以启用对于@AspectJ注解的支持,Spring会自动为匹配的Bean创建代理。

    小结:

    1、被注解的java类当做Bean实例,Bean实例的名称默认是Bean类的首字母小写,其他部分不变。@Service也可以自定义Bean名称,但是必须是唯一的!

    2、尽量使用对应组件注解的类替换@Component注解,在spring未来的版本中,@Controller,@Service,@Repository会携带更多语义。并且便于开发和维护!

  • 相关阅读:
    猫与老鼠的故事(委托)
    返回类型协变和参数类型逆变
    HTTP 方法:GET 对比 POST
    Ajax
    django(未解决的问题)
    mysql开机启动
    apache的不同路径conf/httpd.conf有什么区别【转载】
    Apache部署Django过程中遇到的一些问题
    执行django-admin.py startproject XXX报错的问题
    yum安装软件的过程中出现的一些问题
  • 原文地址:https://www.cnblogs.com/hujunhui/p/9230577.html
Copyright © 2020-2023  润新知