java 注解 优先级_关于java:Spring第四天BeanPostProcessor源码分析彻底搞懂IOC注入及注解优先级问题...

点击下方原文链接查看:

不要再说不会Spring了!Spring第一天,学会进大厂!

Spring第二天,你必须晓得容器注册组件的几种形式!学废它吊打面试官!

Spring第三天,详解Bean的生命周期,学会后让面试官无话可说!

明天解说Spring底层对BeanPostProcessor的应用。

背景:BeanPostProcessor是什么?有什么用?

Spring所有对Bean的解决,BeanPostProcessor接口都贯通其中,都离不开该接口。BeanPostProcessor接口能够治理bean工厂内所有beandefinition(未实例化)数据,可任意批改属性。

首先来看一下有哪些类实现了BeanPostProcessor接口

能够从上图看出,有这么多的接口及类都实现了BeanPostProcessor接口,明天重点来解说ApplicationContextAwareProcessor类、BeanValidationPostProcessor类、InitDestoryAnnotationBeanPostProcessor类的原理。其中ApplicationContextAwareProcessor类是为一些Aware类型的接口,注入对应的属性值。此类帮咱们组件IOC容器,是一个后置处理器,跟进ApplicationContextAwareProcessor类咱们发现,这个后置处理器其实就是判断咱们的bean有没有实现ApplicationContextArea接口,并解决相应的逻辑,所有的后置处理器的原理都是如此。

(其余的类和接口在这里暂且不探讨,重点关注ApplicationContextAwareProcessor类是如何帮忙组件IOC容器的。ps:单词都很长,肯定要留神辨别对应的类和接口)

一、ApplicationContextAwareProcessor实现剖析

问题:ApplicationContextAwareProcessor如何帮忙咱们组件IOC容器呢?

答复:只须要实现ApplicationContextAware接口即可。

定义实体类Plane.java类

咱们再来剖析一下ApplicationContextAwareProcessor类的源码办法

1. 在创立Plane对象,并且还没有初始化之前,先判断是否是实现了ApplicationContextAware接口,如果实现了的话,就调用invokeAwareInterfaces()办法,并给外面注入值。

接下来咱们进入invokeAreaInterfaces()办法,判断是哪一个aware,如果是ApplicationContextAware,就将以后的bean转成ApplicationContextAware类型,调用setApplicationContext(),把plane注入到IOC容器中去。

3. 通过debug调用,测试用例打断点来调试:

也能够用debug调用栈来剖析。

ps:debug能够打在ApplicationContextAwareProcessor处理器类的PostProcessorsBeforeInitialization()办法里,便于调试,当bean为plane类型时,F5跟进看,最终在InvokeAwareInterfaces()办法里返回咱们的IOC容器applicationContext。

二、BeanValidationPostProcess实现剖析

该类次要用于数据校验,当创立完对象,给bean赋值后,在Web用的特地多;把页面提交的值进行校验。

通过源码能够从BeanValidationPostProcess类中能够看到87和95行,有postProcessBeforeInitialization() 和 postProcessAfterInitialization() 办法,这两个办法别离在bean初始化之前 和 初始化之后进行校验。

三、InitDestoryAnnotationBeanPostProcessor实现剖析

此类用来解决JSR250(JDK提供)标准中@PostConstruct 和 @PreDestory,怎么晓得这两注解是前后开始调用的呢?

定义实体类Jeep.java类

以@PostConstruct为例,为什么申明了这个注解之后,就能够找到初始化init办法呢?

继续执行,执行到invokeInitMethods()办法中能够看到,利用反射调用了该办法

从下面的debug调试能够得悉,InitDestoryAnnotationBeanPostProcessor来解决了这两个注解是前后开始调用的。

接下来,咱们来理解一下@Autowired主动拆卸

四、@Autowired主动拆卸

什么是主动拆卸?主动拆卸:Spring利用依赖注入(DI),实现对IOC容器中的各个组件的依赖关系赋值。

新建TestController.java 、TestService.java 、 TestDao.java 类别离建设在指定包内,通过配置类,将所有这些Java对象扫描后保留在IOC容器中治理。

2. 新建配置类,扫描并将以上bean都扫描并加载到容器中

针对以上类建设实现后,在TestService.java中,应用@Autowired注入,并把testDao打印进去

4. 新建测试类,比拟TestService 拿到testDao与间接从容器拿到的testDao是否为同一个?

后果很显著,打印进去是同一个testDao,地址一样

小结:

@Autowired示意默认优先按类型去容器中找对应的组件,相当于anno.getBean(TestDao.class)去容器中获取id为testDao的bean,并注入到TestService的bean中;

应用形式如下:

public class TestService {

// 默认去容器中找testDao的bean` `@Autowired` private TestDao testDao;

}

5. 注意事项

5.1 如果容器中找到多个testDao,会加载哪一个testDao呢?

操作步骤

在配置类申明@Bean(“testDao2”)

并将TestDao退出flag属性和get、set以及toString()办法,用来分辨加载了哪个bean。

如何辨别TestService是应用了(@Reponstry的testDao的flag=1)的bean还是(testDao2的flag=2)的bean?

测试步骤如下:

间接应用@Autowired, 将testDao注入到TestService

bean id为testDao,依据id默认去找@Reponsitory注解的testDao

测试后果为:

service…testDao…TestDao [flag=1]

2. 如果肯定要应用容器中的testDao2呢?操作如下:

将bean id指向testDao2即可

测试后果为:

service…testDao…TestDao [flag=2]

尽管以上定义了private TestDao testDao2, 但还是想加载bean id为testDao(flag=1)的bean,怎么办?此时能够应用@Autowired和@Qualifier联合来指定注入哪一个bean,

操作如下:

通过应用@Qualifier注解,指定加载testDao

测试后果:

service…testDao…TestDao [flag=1]

如果容器中没有任何一个testDao, 会呈现什么情况呢?

操作如下: 正文掉@Repository和@Bean(“testDao2”)

此时容器启动时这两个bean都不会加载(因为注解被正文啦…….)

测试后果如下:

很显著报错了, 因为@Autowired注解里的属性默认required=true.必须找到bean

那怎么解决呢?

将TestService中@Autowired中required设置为false,指定为非必须,当容器中无此bean,也不会报错。

测试后果如下:

null

@Primary注解指定bean如何加载呢?

(注:将以上原正文掉的@Repository和@Bean(“testDao2”) 复原,见下图)

重要:为了验证@Qualifier与@Primary两注解的加载程序,测试如下:

当对于testDao在容器中同时存在多个时, 且@Qualifier与@Primary注解同时存在,会产生什么呢?

见下操作:  关上@Qualifier与@Primary注解.

测试后果:

TestDao [flag=1]

unit….test….TestDao [flag=2]

此时只能阐明一点: @Qualifier是依据bean id指定获取testDao, 不受@Primary影响

那么@Primary的性能在哪呢?持续测试…..

测试后果:

5.2 除了@Autowired, 是不是还用过@Resource(JSR250)  和@Inject(JSR330)

将Qualifier和Autowired正文掉(留神: 此时@Primary 还没正文……)

测试后果:

成果也是一样的, 但它不先优先拆卸@Primary的bean

小结:@Resource和Autowired的区别如下:

@Resource和Autowired一样能够拆卸bean

@Resource毛病:

① 不能反对@Primary性能

② 不能反对@Autowired(required = false)的性能

当然也能够在TestService里按以下形式指定要注入的Bean

测试后果:

5.3 @Inject主动拆卸的应用:

注:@Inject与@Autowired的区别如下:

@Inject和Autowired一样能够拆卸bean, 并反对@Primary性能, 可用于非spring框架.

@Inject毛病: 但不能反对@Autowired(required = false)的性能,须要引入第三方包javax.inject

操作步骤:

1,pom.xml导入javax.inject包

2,应用@Inject注解

论断:@Inject不反对required=false,  但反对primary

Autowired属于spring的, 不能脱离spring,  @Resource和@Inject都是JAVA标准

举荐大家应用@Autowired

这一章节​比拟生涩难懂。能够在下方留言进行一起沟通探讨。

(来自享学IT的​总结)

浏览原文:Spring第四天,BeanPostProcessor源码剖析,彻底搞懂IOC注入及注解优先级问题!

今天将会介绍一章重头戏,AOP底层介绍,实践实际​。

关注公众号【Java极客思维】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值