Spring的注入方式大比拼

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

写在前面,原谅我图片党了。只是喜欢里边一句

一知半解比一无所知更痛苦。”——West World


在使用Spirng 注入的时候,多数情况下都不会在xml中去定义了,而是以注解的方式去声明bean,然后声明依赖的bean,就像下面这样

Spring的注入方式大比拼

如此多的注入方式,你一定花了眼,貌似功能都差不多,但既然都同时存在,那就一定有它的区别,我们来看下区别在哪?


先看下这几个注解的出处


  • @Autowired @Qualifier都是spring专属的,注意@Qualifier有两个,上图中用到的是Spring的,还有一个javax.inject.Qualifier(JSR330)是用来自定义注解的,不能作用于field

  • @Resource 是出自JSR250
    Declares a reference to a resource, e.g. a database

  • @Inject 出自JSR330


知道了出处,再来看下在Spring中实现的细节


Autowired

这个注解的处理是在AutowiredAnnotationBeanPostProcessor

这个类同时还处理了其它的@Inject @Value,所以这几个注解的查找依赖bean逻辑类似

Spring的注入方式大比拼

这段代码在DefaultListableBeanFactory中,它寻找依赖的过程大致如下

根据根据在beanFactory中按类型查找可能被注入的bean,如果有一个类型定义了多个bean,那么返回的是beanName跟beanInstance的map

Spring的注入方式大比拼

判断返回map中bean个数:

  1. 0个 抛 NoSuchBeanDefinitionException

  2. 大于1个,则要去进一步筛选

  3. 恰好有一个,直接选用

Spring的注入方式大比拼

当大于1个的时候,进一步筛选逻辑

  1. 先判断这些bean有没有primary的

  2. 再判断它们有没有priority

  3. 都没有的话,最后根据name匹配(beanFactory中的name与Autowired的属性名)

如果都匹配不到,则返回null,上层方法会throw NoUniqueBeanDefinitionException

Spring的注入方式大比拼


Qulifier

这个是作为一种@Autowired注入方式的一种补充,能在容器中声明了同一类型的多个bean的时候,根据Qualifier的注解中的value 去跟bean name匹配来限定注入哪一个bean,需要说明的是,这里做qualifier判定的时候,同时support了spring的Qualifier和javax.inject.Qulifier

Spring的注入方式大比拼

它的处理逻辑是在Autowired的处理逻辑里做了一层检查,当声明了@Qualifier时,直接过滤掉name不匹配的

Spring的注入方式大比拼

Resource

这个注解的处理逻辑是在CommonAnnotaionBeanPostProcessor中(此类一并处理了其它JSR250的一些注解),它对依赖bean的查找方式与Autowired相同,都是由DefaultListableBeanFactory中的逻辑实现的,所以Qualifier同样适用于Resource,这里就不再贴代码。

BTW,从高内聚低耦合的原则出发,推荐使用JSR标准注解



Spring的注入方式大比拼


欢迎关注,期待与您的交流,让我们携手在通往牛逼的小路上徐徐前行。