一、spring注解驱动开发详解

目前企业中大都使用注解进行开发,此处对开发中用到的spring注解进行一个总结

1、@Configuration和@Bean

@Configuration标注在一个类上,表示这是一个配置类,相当于使用xml时候的配置文件。@Bean给容器中注册一个bean,类型为返回值的类型,id默认使用方法名作为id。可使用@Bean(" ")的形式制定bean的id。

2、@ComponentScan与@ComponentScans

@ComponentScan表示自动扫描组件,标注了@ComponentScan注解,指定扫描哪些包,就可以使用@Controller,@Component,@Service等注解。注解中的属性值主要用到以下几种
  ①value:指定要扫描的包

  ②excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件

  ③includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件,使用该属性的使用,要设置useDefaultFilters = false,表示不使用默认的过滤

  ④FilterType.ANNOTATION:按照注解

  ⑤FilterType.ASSIGNABLE_TYPE:按照给定的类型;

  ⑥FilterType.ASPECTJ:使用ASPECTJ表达式

  ⑦FilterType.REGEX:使用正则指定

  ⑧FilterType.CUSTOM:使用自定义规则

自定义规则的过滤要自定义类并实现TypeFilter接口,实现match方法

@ComponentScans:可包含多个@ComponentScan

3、@Scope与@Lazy

@Scope是设置组件作用域,常用的有以下两种

(1)singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿。

(2)prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。  每次获取的时候才会调用方法创建对象。

@Lazy表示懒加载,即容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化,以后使用直接从容器中获取。只有当作用域是singleton的时候,@Lazy才有效果。

4、@Conditional

@Conditional表示按照条件注册bean。需要自己单独写一个条件类,实现Condition接口,实现matches方法。

@Conditional标注在注册bean的方法上表示按照一定的条件进行判断,满足条件给容器中注册bean

@Conditional标注在类上表示满足条件,这个类中配置的所有bean注册才能生效

5、@Import

@Import表示给容器中导入组件,id默认是组件的全类名。可以单独导入,也可以自定义ImportSelector的子类,进行自定义批量导入,或者定义ImportBeanDefinitionRegistrar的子类,进行自定义批量导入。

自定义ImportSelector的子类,进行自定义批量导入

或者定义ImportBeanDefinitionRegistrar的子类,进行自定义批量导入

6、使用FactoryBean注册组件

需要自定义一个实现了FactoryBean接口的工厂bean,默认获取到的是工厂bean调用getObject创建的对象,要获取工厂Bean本身,我们需要给id前面加一个&

总结:目前给容器中注册组件的方式有以下几种

/**
 * 给容器中注册组件;
 * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
 * 2)、@Bean[导入的第三方包里面的组件]
 * 3)、@Import[快速给容器中导入一个组件]
 *        1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
 *        2)、ImportSelector:返回需要导入的组件的全类名数组;
 *        3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
 * 4)、使用Spring提供的 FactoryBean(工厂Bean);
 *        1)、默认获取到的是工厂bean调用getObject创建的对象
 *        2)、要获取工厂Bean本身,我们需要给id前面加一个&
 *           &colorFactoryBean
 */

7、bean的生命周期相关注解

bean的生命周期:bean创建---初始化----销毁的过程 ,容器进行管理bean的生命周期;

我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。bean对象已被创建,属性已经被复制,才会进行bean的初始化。

当组件是单实例时容器关闭的时候 进行销毁,组件是多实例的时候 ,容器不会管理这个bean的销毁,不会调用销毁方法。

1)、指定初始化和销毁方法;通过@Bean指定init-method和destroy-method;

2)、通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);

3)、使用JSR250。 @PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化方法 。@PreDestroy:在容器销毁bean之前通知我们进行清理工作

4)、BeanPostProcessor。定义一个实现BeanPostProcessor的后置处理器。在bean初始化前后调用。

BeanPostProcessor.postProcessBeforeInitialization:在bean初始化之前调用,即bean对象已创建,属性已赋值,但bean的初始化方法(如前面定义的init等标了初始化注解的方法)还没有执行。

BeanPostProcessor.postProcessAfterInitialization:在bean初始化之后调用,即bean对象已创建,属性已赋值,bean的初始化方法已执行。

BeanPostProcessor原理

遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization,  一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization。

bean的生命周期控制总结:

1)、指定初始化和销毁方法,通过@Bean指定init-method和destroy-method;
2)、通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);
3)、可以使用JSR250,@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法。@PreDestroy:在容器销毁bean之前通知我们进行清理工作
4)、BeanPostProcessor【interface】:bean的后置处理器;在bean初始化前后进行一些处理工作;postProcessBeforeInitialization:在初始化之前工作,postProcessAfterInitialization:在初始化之后工作。

spring底层对BeanPostProcessor的使用:bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor等;

8、@Value和@PropertySource

使用@Value赋值:1、基本数值   2、可以写SpEL #{}   3、可以写${},取出配置文件【properties】中的值(在运行环境变量里面的值)

@PropertySource:使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值。上边的@Value注解中的${}就是从配置文件中获取的

9、@Autowired和@Qualifier

Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值。

 1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值 。

 2)、如果找到多个相同类型的组件,则按照属性名称去查找,即将属性的名称作为组件的id去容器中查找 applicationContext.getBean("bookDao") 

 3)、@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名

 4)、自动装配如果容器中没有这个组件就会报错,可以使用@Autowired(required=false);

 5)、@Primary:首选bean,即让Spring进行自动装配的时候,如果存在多个该类型的组件,默认使用首选的bean。 

 也可以继续使用@Qualifier指定需要装配的bean的名字 (优先按照@Qualifier)

10、@Resource(JSR250)和@Inject(JSR330)[java规范的注解]

@Resource:  可以和@Autowired一样实现自动装配功能,默认是按照组件名称进行装配的,没有能支持@Primary功能,没有像@Autowired那样可以设置reqiured=false。

@Inject:  需要导入javax.inject的包,和Autowired的功能一样。能支持@Primary功能,但没有required=false的功能。

@Autowired是Spring定义的, @Resource、@Inject都是java规范。底层使用了AutowiredAnnotationBeanPostProcessor,解析完成自动装配功能。

11、详解@Autowired与底层组件的使用

@Autowired注解可以放在构造器,参数,方法,属性。放在这些位置都是从容器中获取参数组件的值。

1)、[标注在方法位置]:@Bean+方法参数,参数从容器中获取,默认可以不写@Autowired,效果都是一样的,都能自动装配。

标注在方法上,Spring容器创建当前对象,就会调用方法完成赋值。方法中使用的参数,自定义类型的值从ioc容器中获取

如:

 

2)、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取。

默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作。但如果组件只有一个有参构造器,就会调用有参构造器来创建对象。有参构造器中的参数默认从容器中获取。

自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx), 需要实现xxxAware。在创建对象的时候,会调用接口规定的方法注入相关组件;Aware; * 把Spring底层一些组件注入到自定义的Bean中;。

此处注入的spring底层组件就是当前容器中正在使用的这一个底层组件。

* xxxAware:底层使用后置处理器实现(对应xxxProcessor)。比如 ApplicationContextAware底层由ApplicationContextAwareProcessor实现;

12、@Profile

Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能。@Profile注解指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件。

1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境。 

2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效 。不是指定的环境,配置类不生效。

3)、没有标注环境标识的bean在,任何环境下都是加载的。

激活环境

13、AOP

AOP:动态代理,指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。

使用AOP注解版流程:

1、导入aop模块;Spring AOP:(spring-aspects) 

2、定义一个业务逻辑类(MathCalculator),在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)

3、定义一个日志切面类(LogAspects),切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行。

 切面类里的方法称为通知方法:

 前置通知(@Before):logStart:在目标方法(div)运行之前运行

 后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)

 返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行

 异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行 

 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())

通知方法运行的顺序一般为:前置通知--》方法执行--》后置通知--》返回通知

或:前置通知--》方法执行--》后置通知--》异常通知

 4、给切面类的目标方法标注何时何地运行(通知注解)

 5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中。

 6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)

 [7]、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】 * 在Spring中很多的 @EnableXXX;

主要记住三步

三步:
*  1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
*  2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
*  3)、开启基于注解的aop模式;@EnableAspectJAutoProxy

标注@Pointcut的方法,在本类引用时,直接写方法名即可(比如pointCut()),在其他类中应用需要写方法的全类名(比如com.atguigu.aop.LogAspects.pointCut())

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值