Spring 常用注解

现在特别流行的springboot大量使用注解,实现自动配置简化第三方集成的复杂性。现在总结一下spring中的常用注解

组件注解

  • @Component
  • @Controller
  • @Service
  • @Repository

组件扫描注解

  • @ComponentScan

bean相关注解

  • @Scope
  • @DependsOn
  • @Lazy

bean(singleton作用域)的生命周期的行为注解

  • @PostConstruct
  • @PreDestroy

自动装配

  • @Resource
  • @Autowired
  • @Qualifier

AOP 相关注解

  • @Aspect
  • @Before
  • @AfterReturning
  • @AfterThrowing
  • @After
  • @Arround
  • @Pointcut
  • @Order
    Java配置类相关注解

  • @Configuration

  • @Import
  • @ImportResource
  • @Bean
  • @Value
@Component(“xxx”)

指定某个类是容器的bean,@Component(value="xx")相当于<bean id="xx" />,其中value可以不写。用于标注类为容器bean的注解有四个,主要用于区别不同的组件类,提高代码的可读性
@Component,用于标注一个普通的类
@Controller 用于标注一个控制器类
@Service 用于标注业务逻辑类
@Repository 用于标注DAO数据访问类
现在这几个注解没有什么区别,尽量根据类的不同功能选择合适的注解。
注解用于修饰类,当不写value属性值时,默认值为类名首字母小写。

@Scope(“prototype”)

该注解和@Component这一类注解联合使用,用于标记该类的作用域,默认singleton。也可以和@Bean一起使用,此时@Scope修饰一个方法。关于@Bean稍后有说明

@Lazy(true)

指定bean是否延时初始化,相当于<bean id="xx" lazy-init=""> ,默认false。@Lazy可以和@Component这一类注解联合使用修饰类,也可以和@Bean一起使用修饰方法
:此处初始化不是指不执行init-method,而是不创建bean实例和依赖注入。只有当该bean(被@Lazy修饰的类或方法)被其他bean引用(可以是自动注入的方式)或者执行getBean方法获取,才会真正的创建该bean实例,其实这也是BeanFactory的执行方式。

@DepondsOn({“aa”,”bb”})

该注解也是配合@Component这类注解使用,用于强制初始化其他bean

@DepondsOn("other")
@Lazy(true)
@Controller
@Scope("prototype")
public class UserAction{
    ...............
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

上面的代码指定,初始化bean “userAction”之前需要先初始化“aa”和“bb”两个bean,但是使用了@Lazy(true)所以spring容器初始化时不会初始化”userAction” bean。

@PostConstructor和@PreDestroy

@PostConstructor@PreDestroy这两个注解是jee规范下的注解。这两个注解用于修饰方法,spring用这两个注解容器中spring生命周期行为。

  • @PostConstructor 从名字可以看出构造器之后调用,相当于<bean init-method="">。就是在依赖注入之后执行
  • @PreDestroy 容器销毁之前bean调用的方法,相当于<bean destroy-method="">
@Resource(name=”xx”)

@Resource 可以修饰成员变量也可以修饰set方法。当修饰成员变量时可以不写set方法,此时spring会直接使用jee规范的Field注入。
@Resource有两个比较重要的属性,name和type

  • 如果指定了name和type,则从Spring容器中找到唯一匹配的bean进行装配,找不到则抛出异常;
  • 如果指定了name,则从spring容器查找名称(id)匹配的bean进行装配,找不到则抛出异常;
  • 如果指定了type,则从spring容器中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常;
  • 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配

如果没有写name属性值时
- 修饰成员变量,此时name为成员变量名称
- 修饰set方法,此时name 为set方法的去掉set后首字母小写得到的字符串

@Autowired(required=false)

@Autowired可以修饰构造器,成员变量,set方法,普通方法。@Autowired默认使用byType方式自动装配。required标记该类型的bean是否时必须的,默认为必须存在(true)。
可以配合@Qualifier(value="xx"),实现按bean id注入。

  • required=true(默认),从spring容器查找和指定类型匹配的bean,匹配不到或匹配多个则抛出异常
  • 使用@Qualifier("xx"),则会从spring容器匹配类型和 id 一致的bean,匹配不到则抛出异常

@Autowired会根据修饰的成员选取不同的类型

  • 修饰成员变量。该类型为成员变量类型
  • 修饰方法,构造器。参数类型,可以有多个参数
//service层,业务逻辑
@Service
public class UserService{

    @Resource(name="userDao")
    private UserDao userDao;
    //@Autowired
    //@Qualifier("userDao")
    //private IUserDao userDao;
    //相对来说使用`@Resource`更简单一些
    .......实际业务.............
}

//dao层,持久化
@Repository
@Lazy(true)
@Scope("singleton")
public class UserDao implements InitializingBean,DisposableBean{
    public UserDao() {
        System.out.println("constructor...................");
    }

    public List<User> listUsers(){
        System.out.println("查询所有用户");
    }
    @PostConstruct
    public void postConstructor() {
        System.out.println("post_constructor.................");
    }

    //覆盖InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("after_properties_set..............");

    }

    @PreDestroy
    public void after() {
        System.out.println("pre_destroty.................");
    }
    //重写DisposableBean方法
    @Override
    public void destroy() throws Exception {
        System.out.println("destry_method.............");
    }
}

//测试类
public class TestAnnotation{
    @Test 
    public void test1(){
        ClassPathXmlApplicationContext application=new ClassPathXmlApplicationContext("applicationContext.xml");
        //配置文件里只有一行就是开启自动扫描” <context:component-scan base-package="com" /> “
        System.out.println("-------------------");
        System.out.println(application.getBean("userDao"));
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
输出结果:
constructor...................
post_constructor.................
after_properties_set..............
-------------------
com.dao.PersonManager@4872669f
pre_destroty.................
destry.............
pre_destroty.................
destry.............
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

可以看到虽然UserDao 使用@Lazy,但是还是在spring容器初始化的时候创建了UserDao实例。原因很简单,因为在UserService中需要注入UserDao,所以在此时创建的UserDao实例也属于延时初始化。在上面我们还使用了两个接口InitializingBean 和DisposableBean,这两个接口用于管理singleton作用域的bean的生命周期,类似init-method和destroy-method。不同之处就是调用的循序不一致。大致顺序 @PostConstructor > InitializingBean > init-method 用于指定bean依赖注入后的行为, @PreDestroy > DisposableBean 》destroy-method 用于定制bean销毁之前的行为

Aop相关注解

该注解是AspectJ中的注解,并不是spring提供的,所以还需要导入aspectjweaver.jar,aspectjrt.jar,除此之外还需要依赖aopalliance.jar

@Aspect

修饰Java类,指定该类为切面类。当spring容器检测到某个bean被@Aspect修饰时,spring容器不会对该bean做增强处理(bean后处理器增强,代理增强)

@Before(“pointcut_expresisson”)

修饰方法,before增强处理。有一个value属性用于指定切入点表达式。用于对目标方法(切入点表达式指定方法)执行前做增强处理。可以用于权限检查,登陆检查

@AfterReturning

修饰方法,afterreturning增强处理。目标方法正常结束后做增强处理
常用属性

  • pointcut/value:定义切入点
  • returning:指定一个参数名,用于接受目标方法正常结束时返回的值。在增强方法中定义同名的参数。
@AfterThrowing

修饰方法,afterthrowing增强处理。当目标程序方法抛出 异常或者异常无法捕获时,做增强处理。
常用属性

  • pointcut/value :指定切入点表达式
  • throwing:指定一个形参,在增强方法中定义同名形参,用于访问目标方法抛出的异常
@After

修饰方法 ,after增强处理。无论方法是否正常结束,都会调用该增强处理(@After= @AfterReturning+@AfterThrowing)。一般用于释放资源。
有一个value属性,用于指定切入点表达式。

@Around

修饰方法, around增强处理。该处理可以目标方法执行之前和执行之后织入增强处理,可以看作时@Before和@AfterReturning的总和。
有一个value属性,指定切入点表达式。
Around增强处理通常需要在线程安全的环境下使用,如果@Before和@AfterReturning可以处理就没必要使用@After Returning。

当定义一个Aound增前处理时,增强方法第一形参需要时ProceedingJoinPoint类型。ProceedingJoin Point有一个Object proceed()方法,用于执行目标方法,返回对象当然也可以为目标方法传递数组参数。

切面类

@Aspect
public class UserAdvice{

    @Pointcut("execution(* com.User*.*(..))")
    public void userAdvice(){}

    @Before(value="userAdvice()")
    public void authority(){
        System.out.println("权限检查。。。");
    }

    @AfterReturning(pointcut="userAdvice")
    public void log(){
        System.out.println("写入日志。。。");
    }

    @After("userAdvice()")
    public void release(){
        System.out.println("资源释放。。。");
    }

    @Around("userAdvice()")
    public void arround(ProceedingJoinPoint joinPoint){
        System.out.println("开启事务。。。");
        joinPoint.proceed(jointPoint.getArgs());
        System.out.println("关闭事务。。。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"   
    xsi:schemaLocation="  
        http://www.springframework.org/schema/beans       
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
        http://www.springframework.org/schema/context   
        http://www.springframework.org/schema/context/spring-context-3.0.xsd  
        http://www.springframework.org/schema/aop  
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">  

    <context:component-scan base-package="com" />  <!--自动扫描-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy><!--开启@AspectJ支持-->
</beans> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

测试类

public class TestAnnotation{
    @Test 
    public void test1(){
        ClassPathXmlApplicationContext application=new ClassPathXmlApplicationContext("applicationContext.xml");
        //配置文件里只有一行就是开启自动扫描” <context:component-scan base-package="com" /> “
       IUserDao userDao = application.getBean("userDao",UserDao.class);
       userDao.listUsers();
    }
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

输出结果

constructor...................
post_constructor.................
after_properties_set..............
开启事务。。。
权限检查。。。
System.out.println("查询所有用户");
关闭事务。。。
资源释放。。。
写入日志。。。
pre_destroty.................
destry.............
pre_destroty.................
destry.............
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

spring aop采用和AspectJ相同的优先顺序织入,进入连接连接点时,具有最高优先级的增强处理先被织入,在退出优先级时最高优先级的增强处理先被执行。

@Order

当不同的切面中的两个增强处理需要在同一个连接点被织入时,spring aop可以指定不同切面类的增强处理优先级。
有一个value属性,指定一个int值,属性值越小优先级越高。

@Pointcut

修饰方法,定义一个切入点,用于被其他增强调用。

切入点的定义和普通定义类似

@Pointcut("execution(* user*(..))")
//使用一个返回值为void,空方法体的方法命名切入点
//public 为修饰符,跟方法的修饰符一致,public 可以在其他切面类中使用该切点,default在同一个包下的切面类中使用该切点
//返回值必须为void , 方法名就是定义的切点名称
public  void userAdvice(){}
  • 1
  • 2
  • 3
  • 4
  • 5

切入点表达式格式:execution(modifiers-pattern? return-type-pattern declaring-type-pattern? method-name(param-pattern) throws-pattern?)
注:?表示出现一次或零次

  • modifers-pattern:指定方法的修饰符,支持通配符,可以省略
  • return-type-pattern ;方法返回值类型,必写可以使用通配符*,表示所有返回值类型
  • declaring-type-pattern:全限定类名。可以省略,表示所有类。可以使用通配符。 com.example.dao.User*,表示 匹配com.example.dao包下,所有以User开头的类
  • method-name:指定方法名,必写。可以使用通配符*,表示所有方法。
  • param-pattern:方法参数,必写。可以使用通配符* ,表示任意一个参数类型。也可以使用通配符..,表示零个或多个任意类型的参数。(*,String),表示第一个参数类型任意,第二个必须为String类型。
  • throws-pattern:方法抛出异常,可以省略

下面的注解spring boot中用到的比较频繁

@Configuration

修饰一个Java类,被修饰的类相当于一个xml文件。在springboot中大量使用了该注解,该注解提供了一种使用Java类方式配置bean。

@Import({xxx.class})

修饰Java类,用于向当前配置类导入其他java配置类

@ImportResource(”classpath: /aa.xml“)

修饰Java类,用于向当前注解类导入xml配置文件

上面两个都是用于配置的导入相当于<import resource="">元素

@Bean(name=”xxx”)

修饰方法,该方法的返回值定义为容器中的bean。该注解相当于<bean />元素
常用的属性

  • name:bean id 。name可以省略,省略时name值为方法名。
  • autowire: 是否自动注入,默认Autowire.NO
  • initMethod:bean的初始化方法。在依赖注入之后执行<bean id="" init-method="">
  • destroyMethod: spring容器关闭时bean调用的方法 <bean id="" destroty-method="">
    当然@Bean还可以配合@Scope指定bean的作用域
@Configuration
public class UserConfiguration{

    @Bean(name="userDao")
    public UserDao userDao(){
        return new UserDao();
    }

    @Bean
    public UserService userService(){
        UserService service=new UserService();
        service.setUserDao(userDAo());
        return service;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
@Value(“${expression}”)

修饰成员变量或者 方法构造器的参数,常用于注入属性文件中的值。
注意@Value不能对 static 属性注入。

参考文献 :
李刚.轻量级Java EE [M].第4版.北京:电子工业出版社, 2016

--------------------- 本文来自 柳风123 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/yamadeee/article/details/80381092?utm_source=copy

posted @ 2018-10-08 11:25  砂糖橘子君  阅读(473)  评论(0编辑  收藏  举报