首页 > 代码库 > Spring @AutoWired实现原理

Spring @AutoWired实现原理

昨晚在使用JUnit测试AOP实现时,出现一个问题。在JUnit使用@AutoWired注入某一个对象,Bean Factory里面有该接口的多个实现,Spring不报错,而始终注入的是一个实现类的实例。
这种只能分析一下Spring @AutoWired的实现原理来解决了。

1. 在JUnit测试用例实现下setter方法,使用setter进行注入
2. 在setter方法上添加断点
3. 断点跟踪调试

下面是分析过程:
------------

@AutoWired注解源码分析:

1. Spring为ITestServicce注入对象
Spring调用AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(Object, String, PropertyValues) line: 600

2. 获取注入的setter方法
3. 获取setter方法要注入的参数
4. Spring调用BeanFactory的resolveDependency分析ITestService的依赖
5. BeanFactory调用findAutowiredCandidates为com.itheima.service.TestQ查找ITestService的候选Bean
6. 找到三个候选人[testService2, testService, testServiceProxy]
7. BeanFactory调用determineAutowireCandidate/determinePrimaryCandidate来选择一个匹配的候选Bean(找@Primary标记的bean)
/**
* Return whether the bean definition for the given bean name has been
* marked as a primary bean.
* @param beanName the name of the bean
* @param beanInstance the corresponding bean instance (can be null)
* @return whether the given bean qualifies as primary
*/
8. BeanFactory调用determineHighestPriorityCandidate来选择一个优先级最高的候选Bean(Bean要实现Ordered接口)
/**
* Determine the candidate with the highest priority in the given set of beans. As
* defined by the {@link org.springframework.core.Ordered} interface, the lowest
* value has the highest priority.
* @param candidateBeans a Map of candidate names and candidate instances
* that match the required type
* @param requiredType the target dependency type to match against
* @return the name of the candidate with the highest priority,
* or {@code null} if none found
* @see #getPriority(Object)
*/
9. 根据field或者setter参数的名称进行匹配,如果名字匹配上了,就返回指定的对象,如果没找到则报错。
/**
* Determine the name of the wrapped parameter/field.
* @return the declared name (never {@code null})
*/

被@AutoWired修饰的field或者是setter,如果名字和某一个BeanFactory中的name/id一致,则即使有个实现,也会获取到对应那个名称的Bean。

根据源码分析,要解决代理无法注入的方法有三种:
1. 在代理的<bean>上添加primary="true"属性
2. 使用@Qualifier或者@Resource指定要注入的bean的名字

 

Spring @AutoWired实现原理