写在前面,原谅我图片党了。只是喜欢里边一句
“一知半解比一无所知更痛苦。”——West World
在使用Spirng 注入的时候,多数情况下都不会在xml中去定义了,而是以注解的方式去声明bean,然后声明依赖的bean,就像下面这样
如此多的注入方式,你一定花了眼,貌似功能都差不多,但既然都同时存在,那就一定有它的区别,我们来看下区别在哪?
先看下这几个注解的出处
-
@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逻辑类似
这段代码在DefaultListableBeanFactory中,它寻找依赖的过程大致如下
根据根据在beanFactory中按类型查找可能被注入的bean,如果有一个类型定义了多个bean,那么返回的是beanName跟beanInstance的map
判断返回map中bean个数:
-
0个 抛 NoSuchBeanDefinitionException
-
大于1个,则要去进一步筛选
-
恰好有一个,直接选用
当大于1个的时候,进一步筛选逻辑
-
先判断这些bean有没有primary的
-
再判断它们有没有priority
-
都没有的话,最后根据name匹配(beanFactory中的name与Autowired的属性名)
如果都匹配不到,则返回null,上层方法会throw NoUniqueBeanDefinitionException
Qulifier
这个是作为一种@Autowired注入方式的一种补充,能在容器中声明了同一类型的多个bean的时候,根据Qualifier的注解中的value 去跟bean name匹配来限定注入哪一个bean,需要说明的是,这里做qualifier判定的时候,同时support了spring的Qualifier和javax.inject.Qulifier
它的处理逻辑是在Autowired的处理逻辑里做了一层检查,当声明了@Qualifier时,直接过滤掉name不匹配的
Resource
这个注解的处理逻辑是在CommonAnnotaionBeanPostProcessor中(此类一并处理了其它JSR250的一些注解),它对依赖bean的查找方式与Autowired相同,都是由DefaultListableBeanFactory中的逻辑实现的,所以Qualifier同样适用于Resource,这里就不再贴代码。
BTW,从高内聚低耦合的原则出发,推荐使用JSR标准注解
欢迎关注,期待与您的交流,让我们携手在通往牛逼的小路上徐徐前行。