写在前面:阅读spring源码需要读者对Java反射和动态代理有一定了解。关于这部分内容,可以参考这篇博客:Spring源码分析准备工作及java知识补充
一、Spring依赖注入的方式
关于spring的依赖注入,可以参考官方文档:Spring依赖注入
Spring中的依赖注入主要基于两种两种主要的变体: 基于构造器的依赖注入和基于Setter的依赖注入。
(1)通过构造进行依赖注入
package x.y;
public class ThingOne {
public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
// ...
}
}
xml配置方式
<beans>
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg ref="beanTwo"/>
<constructor-arg ref="beanThree"/>
</bean>
<bean id="beanTwo" class="x.y.ThingTwo"/>
<bean id="beanThree" class="x.y.ThingThree"/>
</beans>
在一个Bean只有一个有参构造器时,Spring自动会根据构造器参数的Class类型去容器中找到匹配的Bean进行注入。
当构造器的参数类型是基本数据类型(int,String),构造器无法匹配Spring容器中的Bean进行注入,需要手动配置构造器参数类型和参数值。
package examples;
public class ExampleBean {
// Number of years to calculate the Ultimate Answer
private final int years;
// The Answer to Life, the Universe, and Everything
private final String ultimateAnswer;
//@ConstructorProperties注释可以显式命名构造函数参数名(name)
@ConstructorProperties({"years", "ultimateAnswer"})
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}
xml中配置构造器的参数类型和参数值。
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
如果参数类型存在歧义,可以使用index属性指定入参顺序,或者通过name属性指定参数名称
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
或
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>
(2)通过Setter进行依赖注入
Service service;
……
//set注入
public void setService(Service service) {
this.service = service;
}
然后在xml配置文件中为该属性设置值
<bean id="myService" class="cn.crazy.service.MyService">
<property name="service" ref="service"></property>
</bean>
<bean id="service" class="cn.crazy.service.impl.serviceImpl"></bean>
当然我们也Beandefinition为该属性设置值。
@Component
public class MyPostProcessor implements BeanFactoryPostProcessor {
@Autowired
Service service;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition beanDefinition = (GenericBeanDefinition)beanFactory.getBeanDefinition("myService");
/**
* 设置属性值
*/
beanDefinition.getPropertyValues().addPropertyValue("service",service);
}
在日常开发中,我们更多的是使用Setter进行可选依赖的注入,而不是必须的。如果希望Setter的依赖注入是必须的,可以在Setter上加@Autowired注解。
(3)构造器依赖注入与Setter依赖注入的区别
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现。使用构造器进行依赖注入时,如果依赖不存在,会抛出异常。
- 可选依赖使用setter注入进行,灵活性强。
- Spring 团队通常提倡构造函数注入,因为它允许您将应用程序组件实现为不可变对象,并确保所需的依赖项不为空。构造函数注入的组件总是以完全初始化的状态返回给调用代码,所以如果构造器注入的依赖存在循环依赖,会报错。
- 构造函数注入是在对象创建时就完成了依赖注入,而setter注入可以在对象创建后任何时候完成依赖注入。
综上所述,构造函数注入和setter注入各有优缺点,开发人员可以根据自己的需求选择最适合的方式。通常情况下,如果依赖对象是不可变的,则应该使用构造函数注入;如果依赖对象是可变的,则应该使用setter注入。
二、Spring自动装配
关于spring的自动装配,可以参考官方文档:Spring自动装配
(1)Spring自动装配简介
我们把 Spring 在 Bean 与 Bean 之间建立依赖关系的行为称为“装配”。Spring自动装配(Spring Autowiring)是一种通过自动连接bean之间的依赖关系来简化Spring应用程序开发的技术。
- Spring 的自动装配功能可以让 Spring 容器依据某种规则(自动装配的规则,有五种),为指定的 Bean 从应用的上下文(AppplicationContext 容器)中查找它所依赖的 Bean,并自动建立 Bean 之间的依赖关系。而这一过程是在完全不使用任何 <constructor-arg>和 <property> 元素 ref 属性的情况下进行的。
- Spring 的自动装配功能能够有效地简化 Spring 应用的 XML 配置,因此在配置数量相当多时采用自动装配降低工作量。
- Spring 框架式默认不支持自动装配的,要想使用自动装配,则需要对 Spring XML 配置文件中 <bean> 元素的 autowire 属性进行设置。
(2)Spring自动装配方式
自动装配功能有四种方式。您可以指定每个 bean 的自动装配(<bean autowire="XXX">),从而可以选择要自动装配的那些 bean。下表描述了四种自动装配模式:
装配方式 | 说明 |
---|---|
byName | 按名称自动装配。 Spring 会根据的 Bean中对象属性的名称,在整个应用的上下文 ApplicationContext(IoC 容器)中查找。若某个 Bean 的 id 或 name 属性值与这个对象属性的名称相同,则获取这个 Bean,并与当前的 Bean建立关联关系。 |
byType | 按类型自动装配。 Spring 会根据 Bean的对象属性的类型,在整个应用的上下文 ApplicationContext(IoC 容器)中查找。若某个 Bean 的 class 属性值与这个对象属性的类型相匹配,则获取这个 Bean,并与当前的 Bean 建立关联关系。 |
constructor | 与 byType 模式相似,不同之处在与它应用于构造器参数(依赖项),如果在容器中没有找到与构造器参数类型一致的 Bean,那么将抛出异常。 构造器装配方式其实就是根据参数的数据类型,进行 byType 模式的自动装配。 |
no | 默认值,表示不使用自动装配,Bean 的依赖关系必须通过 <constructor-arg>和 <property> 元素的 ref 属性来定义。 |
使用 byType 或构造函数自动装配方式,可以连接数组和集合类型。在这种情况下,容器中匹配预期类型的所有自动装配候选项都被提供以满足依赖关系。如果预期的key类型是 String,则可以自动连接强类型的 Map 实例。自动连接的 Map 实例的值由所有匹配预期类型的 bean 实例组成,Map 实例的key包含相应的 bean 名称。
注意:在使用byName和byType做为自动装配方式时,需要提供属性的Set()方法,否则Spring无法完成自动装配。
代码演示
定义一个Service接口,有两个实现类
public interface Service {
String print();
}
public class ServiceImpl1 implements Service {
@Override
public String print() {
return ServiceImpl1.class.getName();
}
}
public class ServiceImpl2 implements Service{
@Override
public String print() {
return ServiceImpl2.class.getName();
}
}
现在在LearningService 中定义一个属性,在不手动设置值的情况下,如何利用Spring自动装配进行依赖连接。
public class LearningService {
Service service;
/**
* 自动注入模式需要set方法
*
*/
public void setService(Service service) {
this.service = service;
}
//get()方法非必须
public Service getService() {
return service;
}
@Override
public String toString() {
return "LeanningService{" +
"service=" + service.print() +
'}';
}
}
(i)通过byName的方式进行依赖连接
<!--指定自动注入方式为byName-->
<!--将service的实现注册到Spring中,但是没有手动设置依赖关系-->
<bean id="learningService" class="cn.crazy.autowirted.LearningService" autowire="byName">
</bean>
<bean id="service" class="cn.crazy.autowirted.ServiceImpl1">
</bean>
<bean id="service1" class="cn.crazy.autowirted.ServiceImpl2">
</bean>
这样Spring会根据LearningService 的属性的名称(service),找到容器中Bean的id或name与属性名称相匹配,然后将这个Bean注入LearningService中。
Spring中bean的id或name必须唯一,不然抛出如下异常。
所以这种方式是无法将一个接口的多个实现或一个类的多个子类映射到一个数组或集合中的,因为一个name只能对应一个Bean。
(ii)通过byType的方式进行依赖连接
<!--LearningService中有Service类型的成员变量,如果自动注入的方式为byType,Spring中如果存在一个以上Service类型的bean,会报错
[Could not autowire. There is more than one bean of 'Service' type. Beans: service1,service. Properties “service”]
如果自动注入的方式为byName则没有这种问题-->
<bean id="learningService" class="cn.crazy.autowirted.LearningService" autowire="byType">
</bean>
<bean id="service" class="cn.crazy.autowirted.ServiceImpl1">
</bean>
<bean id="service1" class="cn.crazy.autowirted.ServiceImpl2">
</bean>
如果我们选择这种方式进行自动装配,当一个属性对应的Type找到超过一个实现类时,会出现如下异常。
出现这种情况时,我们可以将一个主要实现类作为主要的候选对象,或者将不重要的实现类设置为非主要候选对象。(xml配置文件设置<bean primary="true/false">或添加注解@Primary)
这种方式是可以将一个接口的多个实现或一个类的多个子类映射到一个数组或集合中。
public class LearningService {
Service service;
Map<String,Service> serviceMap;
List<Service> serviceList;
public List<Service> getServiceList() {
if(!this.serviceList.isEmpty() && this.serviceList.get(0) != null){
for (Service service: serviceList) {
System.out.println(service.print());
}
}
return serviceList;
}
public Map<String, Service> getServiceMap() {
if(!this.serviceMap.isEmpty()){
Set<Map.Entry<String, Service>> entries = this.serviceMap.entrySet();
for (Map.Entry<String, Service> service : entries) {
System.out.println("serviceName : " + service.getKey() + ", serviceImpl : " + service.getValue());
}
}
return serviceMap;
}
public void setServiceMap(Map<String, Service> serviceMap) {
this.serviceMap = serviceMap;
}
public void setServiceList(List<Service> serviceList) {
this.serviceList = serviceList;
}
/**
* 自动注入模式需要set方法
*
*/
public void setService(Service service) {
this.service = service;
}
//get()方法非必须
public Service getService() {
return service;
}
@Override
public String toString() {
return "LeanningService{" +
"service=" + service.print() +
'}';
}
}
(iii)通过构造器的方式进行依赖连接
在只要一个依赖的时候,如果提供了一个接口的多个实现,不同于byType,构造器自动装配方式下不会报错。
<bean id="learningService" class="cn.crazy.autowirted.LearningService" autowire="constructor">
</bean>
<bean id="service" class="cn.crazy.autowirted.ServiceImpl1">
</bean>
<bean id="service1" class="cn.crazy.autowirted.ServiceImpl2">
public LearningService(Service service) {
this.service = service;
System.out.println(" service + " + service.print());
}
这种情况下,构造器注入的实现类ServiceImpl1 。如果我们希望注入ServiceImpl2,可以设置primary属性值或加@Primary实现。
有且仅有一个有参构造器的时候,Spring没有选择,只能选择唯一的那个构造器。那有多个有参构造器的时候,Spring会怎样抉择?
推断构造器
关于使用构造器自动装配的方式下进行依赖注入时,Spring如何选择构造器?Spring有一套自己的规则,但首先排除构造器参数中带有基本数据类型(String,Int等)的构造器,因为基本数据类型不能作为Spring中的Bean。
关于构造器的推断,后续章节详细讲。Spring中用一个差异值来对比各个构造器的匹配程度,选出一个Spring认为最优的构造器。在修饰符相同的情况下,Spring会选择参数个数(不包括基本数据类型)最多的那个构造器,可能Spring认为这样可以发挥自动装配的最大作用。如果在构造参数个数相同时,构造器参数的优先级大概为:单个类 > List > Map>Set。
public class LearningService {
private String name;
private Service service;
private Service service1;
private Map<String,Service> serviceMap;
private List<Service> serviceList;
private Set<Service> serviceSet;
public LearningService(String name, Service service, Service service1, Map<String, Service> serviceMap, List<Service> serviceList) {
this.name = name;
this.service = service;
this.service1 = service1;
this.serviceMap = serviceMap;
this.serviceList = serviceList;
System.out.println("name, service , service1 serviceList ,serviceMap constructor ");
}
public LearningService(Service service, Service service1, Map<String, Service> serviceMap, List<Service> serviceList) {
this.service = service;
this.service1 = service1;
this.serviceMap = serviceMap;
this.serviceList = serviceList;
System.out.println("service , service1 serviceList ,serviceMap constructor ");
}
public LearningService(Service service, Service service1) {
this.service = service;
this.service1 = service1;
System.out.println("service , service1 constructor ");
System.out.println("service = " + service.print() + ", service1 = " + service1.print());
}
public LearningService(Service service,Service service1, List<Service> serviceList) {
this.service = service;
this.service1 = service1;
this.serviceList = serviceList;
System.out.println("service , service1 serviceList constructor ");
System.out.println("service = " + service.print() + ", service1 = " + service1.print());
}
public LearningService(Service service,Service service1, Set<Service> serviceSet) {
this.service = service;
this.service1 = service1;
this.serviceSet = serviceSet;
System.out.println("service , service1 serviceSet constructor ");
System.out.println("service = " + service.print() + ", service1 = " + service1.print());
}
public LearningService(Service service,Service service1, Map<String,Service> serviceMap) {
this.service = service;
this.service1 = service1;
this.serviceMap = serviceMap;
System.out.println("service , service1 serviceMap constructor ");
System.out.println("service = " + service.print() + ", service1 = " + service1.print());
}
public LearningService(Service service) {
this.service = service;
System.out.println("service constructor ");
}
public LearningService(List<Service> serviceList) {
this.serviceList = serviceList;
System.out.println("serviceList constructor ");
}
public LearningService(Map<String,Service> serviceMap) {
this.serviceMap = serviceMap;
System.out.println("serviceMap constructor ");
}
}
这里会打印"service , service1 serviceList ,serviceMap constructor "。
(3)修改自动状态的方式
除了在xml中配置default-autowire或autowire属性值外,还可以通过BeanDefinition设置自动装配的方式。
/**
* *AUTOWIRE_NO 0
* AUTOWIRE_BY_NAME 1
* AUTOWIRE_BY_TYPE 2
* AUTOWIRE_CONSTRUCTOR 3
**/
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
可以在创建BeanDefinition对象时指定自动装配的值,也可以通过BeanFactoryPostProcessor后置处理器修改这个值。
三、@Autowired和@Resource进行依赖注入
很多人会把@Autowired和@Resource进行依赖注入也称为自动装配,其实这是不正确的,@Autowired和@Resource进行依赖注入不属于自动装配,通过beanDefinition.getAutowireMode()可以发现加了这两个注解的类的值为AUTOWIRE_NO。
而且在日常的项目中,我们更多的是使用注解的方式进行Spring开发,xml配置的方式会相对少一些,所以使用@Autowired或Resource进行依赖注入更为频繁。
@Autowired和@Resource二者的区别
1)来源不同:@Autowired 来自 Spring 框架,而 @Resource 来自于(Java)JSR-250;
2)依赖查找的顺序不同:@Autowired 先根据类型再根据名称查询,而 @Resource 先根据名称再根据类型查询;
3)支持的参数不同:@Autowired 只支持设置 1 个参数,而 @Resource 支持设置 7 个参数;
4)依赖注入的用法支持不同:@Autowired 既支持构造方法注入,又支持属性注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入;
5)处理注解的后置处理器不同。处理@Resource注解依赖注入的后置处理器是CommonAnnotationBeanPostProcessor,而处理@Autowired注解依赖注入的是 AutowiredAnnotationBeanPostProcessor
- @Autowired查找顺序
- @Resource查找顺序
四、源码分析
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
……
//MutablePropertyValues propertyValues = mbd.getPropertyValues();
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
//底层是List<PropertyValues>.add(pvs);
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
/**
* @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry,Object source)
*/
//调用第六次后置处理器
//这里的BeanPostProcessor是由spring启动时自己注入的,这里使用了策略模式,
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
//应用PropertyValues,将pvs应用于bw中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
(1)byType源码分析
byName和byType的处理逻辑类似,我们选择代码相对复杂的byType源码进行分析。
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//代码块一:返回有set()方法的属性的名字数组
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//获取该属性对应的属性描述器
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
//获取通过byType自动注入依赖项的描述符
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//代码块二:解析自动注入的属性值
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
//代码块九:将解析出来属性名对应的属性值添加到MutablePropertyValues
pvs.add(propertyName, autowiredArgument);
}
//autowiredBeanNames有多个值表示属性类型是数组或集合元素
for (String autowiredBeanName : autowiredBeanNames) {
//这个是往dependentBeanMap中加入一个autowiredBeanName为key,Set<String> dependentBeans为value(beanName添加到Set中)
//dependentBeanMap就是维护了一个autowiredBeanName(key)需要被注入到哪些bean(set)的map集合
//同时也会这往dependenciesForBeanMap中加入一个beanName为key,Set<String> dependenciesForBean为value(autowiredBeanName添加到Set中)
//dependenciesForBeanMap就是维护了一个beanName(key)需要注入哪些bean(set)的map集合
//代码块十:维护依赖关系对应的集合
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
(i)代码块一:unsatisfiedNonSimpleProperties(),返回有set()方法的属性的名字数组。
这个方法是利用Java内省机制返回beanClass中有set()方法的属性名数组。byName也是通过这个方法找到要进行依赖注入的属性名数组,这也是byTye和byName必须提供属性的set()方法的原因。
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues();
//所有的属性描述器,Java内省机制
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
//pd.getWriteMethod()就是setXX()方法,pd.getReadMethod()就是getXX()方法
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
我们知道Java内省获取属性描述器的一般方式需要借助Introspector类,那为什么Spring可以直接通过bw.getPropertyDescriptors()拿到beanClass的属性描述器?
//通过Java获取属性描述器的一般方式
BeanInfo beanInfo = Introspector.getBeanInfo(XXX.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
……
带着这个疑问?我大概看了一下spring源码,因为这块代码也不是今天的重点,大概说一下是怎样实现的。就是在属性填充之前,肯定要先创建实例,spring会在推断合适的构造器用于创建实例,而创建出来的实例beanClass会用BeanWrapper封装
//根据推断出来的构造器及其参数创建bean实例,并封装到bw对象中
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
……
public void setBeanInstance(Object object) {
this.wrappedObject = object;
this.rootObject = object;
this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
setIntrospectionClass(object.getClass());
}
protected void setIntrospectionClass(Class<?> clazz) {
if (this.cachedIntrospectionResults != null && this.cachedIntrospectionResults.getBeanClass() != clazz) {
this.cachedIntrospectionResults = null;
}
}
最后CachedIntrospectionResults(Class<?> beanClass) 的beanClass就是构造器创建的bean实例,也是BeanWrapperImpl的this.wrappedObject的值。
public interface BeanWrapper extends ConfigurablePropertyAccessor {
……
PropertyDescriptor[] getPropertyDescriptors();
}
public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements BeanWrapper {
private CachedIntrospectionResults(Class<?> beanClass) throws BeansException {
try {
if (logger.isTraceEnabled()) {
logger.trace("Getting BeanInfo for class [" + beanClass.getName() + "]");
}
//Java内省机制
this.beanInfo = getBeanInfo(beanClass);
if (logger.isTraceEnabled()) {
logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
}
this.propertyDescriptors = new LinkedHashMap<>();
Set<String> readMethodNames = new HashSet<>();
// beanClass对应的属性描述器
PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (Class.class == beanClass &&
("classLoader".equals(pd.getName()) || "protectionDomain".equals(pd.getName()))) {
// Ignore Class.getClassLoader() and getProtectionDomain() methods - nobody needs to bind to those
continue;
}
if (logger.isTraceEnabled()) {
logger.trace("Found bean property '" + pd.getName() + "'" +
(pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") +
(pd.getPropertyEditorClass() != null ?
"; editor [" + pd.getPropertyEditorClass().getName() + "]" : ""));
}
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
this.propertyDescriptors.put(pd.getName(), pd);
Method readMethod = pd.getReadMethod();
if (readMethod != null) {
readMethodNames.add(readMethod.getName());
}
}
// Explicitly check implemented interfaces for setter/getter methods as well,
// in particular for Java 8 default methods...
Class<?> currClass = beanClass;
while (currClass != null && currClass != Object.class) {
introspectInterfaces(beanClass, currClass, readMethodNames);
currClass = currClass.getSuperclass();
}
// Check for record-style accessors without prefix: e.g. "lastName()"
// - accessor method directly referring to instance field of same name
// - same convention for component accessors of Java 15 record classes
introspectPlainAccessors(beanClass, readMethodNames);
this.typeDescriptorCache = new ConcurrentReferenceHashMap<>();
}
catch (IntrospectionException ex) {
throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex);
}
}
(ii)代码块二/代码块三 :resolveDependency(),解析自动注入的属性值,真正解析属性依赖的方法doResolveDependency()。
@Autowired进行依赖注入也会进行使用到这个方法来解析依赖。resolveMultipleBeans()方法里面也是通过findAutowireCandidates()找到对应的实现类的,不过它会对结果(个数>1)进行排序。
这个方法大致总结为:
1)根据属性的type到spring容器中找到该类型的所有实现类,并封装到matchingBeans中,其中key为属性值,value为属性值对应的实例对象或Class对象。
2)如果找到多于一个实现,推断最终自动装配的属性名,会根据beanClass是否设置了Primary和Priority属性值进行推断,在byType方式下,如果没有设置Primary和Priority属性值,推断出的结果为null,且会抛出异常
3)根据推断出来的属性名,到matchingBeans找到对应的value,如果value是Class,到spring容器中获取对应的bean并返回。
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
……
//如果加了@Lazy注解,产生一个代理对象
//思考:这个代理对象的作用是什么?
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 代码块三 :真正解析属性依赖的方法
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
……
}
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
//shortcut可以理解为一个快照,如果提供了一个快照,直接返回这个快照,不要执行后面繁杂的流程
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//field的类型,这也是Java内省机制
Class<?> type = descriptor.getDependencyType();
//是否有默认值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
……
//这里是实现集合类型的属性注入,如果加了@Order(value = xxx)或实现了PriorityOrdered接口,返回的结合会是有序的结果
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//代码块四:找非集合类型属性匹配的bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//根据type类型找到有多个实现(多态)
if (matchingBeans.size() > 1) {
//代码块七:推断具体注入的beanName,如果是byType注入多个相同类型的,且没有primary和priority处理,这里返回null
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
//@Autowired(required = "ture")表示必须注入,如果无法推断注入的值,抛出异常
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
//代码块八:从容器获取候选实例对象
if (instanceCandidate instanceof Class) {
//如果是Class类型,通过beanFactory.getBean(autowiredBeanName)
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
(iii)代码块四:findAutowireCandidates(),找到非集合类型属性匹配的bean。
这个方法大概可以总结为:
1)根据requiredType类型找到容器中其所有实现类的beanName(如果存在父容器,也会到父容器中找),本质是遍历beanDefinitionNames,找到其中所有requiredType类型的bean对应的名字。同时创建一个Map集合用于存放最终找到的候选对象(result)。
2)遍历this.resolvableDependencies是否有与requiredType匹配的bean,如果有直接从中获取对应的值,并添加到result候选对象map中。(this.resolvableDependencies存放的是spring在beanFactory准备阶段put的元素)
3)遍历找到的候选对象名称,判断是否自身引用和对应的bean定义是否有资格作为自动候选对象,将符合条件的候选对象对应的实例对象或Class对象加入result集合中。
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//通过type(Class)在spring容器中找到对应的type的所有实现类的beanName(如果存在父容器,也会到父容器中找)
// 这个方法的本质是遍历beanDefinitionNames,找到其中所有requiredType类型的beanName
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
//this.resolvableDependencies在beanFactory准备阶段会put一些元素
//看this.resolvableDependencies是否有与requiredType匹配的,如果有直接从中获取对应的值
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
for (String candidate : candidateNames) {
//isSelfReference见名知意,自身引用(candidate==beanName)
//将beanName对应的Class返回(创建)
// 代码五:isAutowireCandidate
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
//代码块六:将符合条件的candidate对应的实例对象或Class对象加入result集合中
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
(iv)代码五:isAutowireCandidate(),确定指定的bean定义是否有资格作为自动候选对象被注入到声明了匹配类型依赖的其他bean中。
这里一般会根据查找出来的candidateBean对应的beanDefinition构建BeanDefinitionHolder对象,一般这个方法都会返回true,因为beanDefinition.isAutowireCandidate()默认true,除非程序员配置了值(autowire-candidate="false",把这个可以注入到其他对象的资格给关闭了)。
/**
* 确定指定的bean定义是否有资格作为自动候选对象被注入到声明了匹配类型依赖的其他bean中。
*/
protected boolean isAutowireCandidate(
String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)
throws NoSuchBeanDefinitionException {
String bdName = BeanFactoryUtils.transformedBeanName(beanName);
//BeanDefinitionMap容器中是否存在这个bean
if (containsBeanDefinition(bdName)) {
return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(bdName), descriptor, resolver);
}
//singletonObjects容器(单例池)中是否存在这个bean
else if (containsSingleton(beanName)) {
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
}
//如果当前容器中没找,到父容器中找
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
}
else if (parent instanceof ConfigurableListableBeanFactory) {
// If no DefaultListableBeanFactory, can't pass the resolver along.
return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
}
else {
return true;
}
}
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {
String bdName = BeanFactoryUtils.transformedBeanName(beanName);
//设置对应BD里面的beanClass值,如果BeanDefinition的beanClass值为空,通过mbd.getBeanClassName()初始化加载对应的Class到beanClass属性中
// 这个方法基本没有用到bdName这个参数
resolveBeanClass(mbd, bdName);
if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
}
BeanDefinitionHolder holder = (beanName.equals(bdName) ?
this.mergedBeanDefinitionHolders.computeIfAbsent(beanName,
key -> new BeanDefinitionHolder(mbd, beanName, getAliases(bdName))) :
new BeanDefinitionHolder(mbd, beanName, getAliases(bdName)));
//private boolean autowireCandidate = true;
return resolver.isAutowireCandidate(holder, descriptor);
}
(v)代码块六: addCandidateEntry(),将符合条件的candidate对应的实例对象或Class对象加入result集合中。
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
if (descriptor instanceof MultiElementDescriptor) {
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
if (!(beanInstance instanceof NullBean)) {
candidates.put(candidateName, beanInstance);
}
}
else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
((StreamDependencyDescriptor) descriptor).isOrdered())) {
//如果spring容器中存在candidateName,通过getBean()返回对应的beanInstance
//为什么会存在?可能其他bean的属性也包含这个candidateName,那个bean已经完成初始化了,candidateName对应的bean被创建了
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
//getType(candidateName)返回bd对应的实现类对应的Class(不是接口的Class)
candidates.put(candidateName, getType(candidateName));
}
}
(vi)代码块七:determineAutowireCandidate(),推断具体注入的beanName。
如果是byType注入多个相同类型的实现,且没有进行primary和priority处理,这里返回null。
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
//如果candidates中的某个bean为primary[<bean primary="true"/>或@Primary],直接返回这个beanname
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
//如果指定了优先级,返回优先级最高的beanname[只对@Priority(value = xx)有效,对@Order(value = xxx)或实现了PriorityOrdered接口无效优先级(集合元素排序)]
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
//matchesBeanName主要判断candidateName(包括别名)与descriptor.getDependencyName()是否匹配
//this.resolvableDependencies.containsValue(beanInstance)如果当前依赖关联里有beanInstance,直接返回对应的candidateName
//当自动装配方式为byType时,descriptor.getDependencyName()为null
//当使用@Autowired进行依赖注入时descriptor.getDependencyName()为属性名称
//这也是@Autowired如果根据type找到多个实现,就会再从这几个实现里找到name与属性名称匹配的candidateName
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
(vii)代码八:resolveCandidate(),从容器中获取候选实例。
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
(viii)代码块九:将解析出来属性名对应的属性值添加到MutablePropertyValues。
bd对象有propertyValues属性,用于存放beanClass的所有的属性的属性名称和属性值。自动装配的本质就是解析出属性名对应的bean,并放入添加到MutablePropertyValues中,最后封装到BeanWrapperImpl的propertyValues属性中。
public MutablePropertyValues add(String propertyName, @Nullable Object propertyValue) {
addPropertyValue(new PropertyValue(propertyName, propertyValue));
return this;
}
(ix)代码块十:registerDependentBean(),维护依赖关系对应的集合。
dependentBeanMap就是维护了一个autowiredBeanName(key)需要被注入到哪些bean(set)的map集合
dependenciesForBeanMap就是维护了一个beanName(key)需要注入哪些bean(set)的map集合
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
(x)代码块十一:convertForProperty(),属性转换
为什么说byName或byType的依赖注入是基于内省实现的?
applyPropertyValues(beanName, mbd, bw, pvs)属性值应用的代码中最后找到将属性名转换为bw中对象属性值的方法convertForProperty()。
public Object convertForProperty(@Nullable Object value, String propertyName) throws TypeMismatchException {
CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
if (pd == null) {
throw new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName,
"No property '" + propertyName + "' found");
}
TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
if (td == null) {
td = cachedIntrospectionResults.addTypeDescriptor(pd, new TypeDescriptor(property(pd)));
}
return convertForProperty(propertyName, null, value, td);
}
(2)@Autowired依赖注入源码分析
为什么说@Autowired和@Resource依赖注入不属于自动装配?
除了@Autowired和@Resource对应的AutowireMode为no,同时byName和byType是通过Java自省机制实现的,而@Autowired和@Resource依赖注入是基于Java反射实现的。
注:@Autowired和@Resource依赖注入的代码逻辑基本相同,这是解析注解稍有差别,这里就只针对@Autowired源码进行分析。
(i)AutowiredAnnotationBeanPostProcessor,解析@Autowired注解依赖注入的后置处理器
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
……
/**
* @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry,Object source)
*/
//调用第六次后置处理器
//这里的BeanPostProcessor是由spring启动时自己注入的,这里使用了策略模式,
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 通过AutowiredAnnotationBeanPostProcessor完成@Autowired注解注入的解析
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
……
if (pvs != null) {
//应用PropertyValues,将pvs应用于bw中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
(ii)postProcessProperties(),在工厂应用给定的属性值之前把它们注入到
指定的bean中
//属性注入
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//this.injectionMetadataCache.get(cacheKey)中获取值,在第三次调用后置处理器时(合并bd),就已经找出所有需要注入点
// 代码块一:找到通过@Autowired注入的属性元数据信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//代码块五:属性注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
(ii)代码块一:findAutowiringMetadata(),找到通过@Autowired注入的对象(Field和Method)的元数据信息
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 是否需要刷新缓存,如果metadata == null或缓存的class与当前的clazz不相同,表示要刷新
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//代码块二:构造自动注入的元数据
metadata = buildAutowiringMetadata(clazz);
//添加缓存
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
(ii)代码块二:buildAutowiringMetadata(),构造自动注入的元数据对象
这个方法大致总结为:
1)遍历targetClass的所有field,如果field上添加了@Autowired注解,判断是否为static类型,如果是,退出遍历。如果不是,获取require属性值,并根据field对象和require属性值构建AutowiredFieldElement对象。
2)遍历targetClass的所有method,如果方法是桥接方法,判断其是否“可见”的桥接方法。如果不是,退出遍历。如果method上添加了@Autowired注解,判断是否为static类型,如果是,退出遍历。如果不是,获取require属性值,并根据field对象和require属性值构建AutowiredFieldElement对象。
3)将fiel和method对应的AutowiredFieldElement添加到elements集合,并通过elements和Class构建InjectionMetadata对象。
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//代码块三:处理field上的@Autowired
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 将属性域上@Autowired的注解信息
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
// @Autowired不支持静态属性域的依赖注入
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 获取@Autowired中required的值
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//代码块四:处理method上的@Autowired
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
//比较桥接方法和它所桥接的方法的签名。如果参数和返回类型是相同的,这是一个“可见”桥接方法
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
(iii)代码块三:doWithLocalFields(),处理field上的@Autowired,将符合要求的field构建成AutowiredFieldElement对象。
public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
for (Field field : getDeclaredFields(clazz)) {
try {
fc.doWith(field);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
}
}
}
(iv)代码块四:doWithLocalMethods(),处理method上的@Autowired,将符合要求的method构建成AutowiredFieldElement对象。
public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
Method[] methods = getDeclaredMethods(clazz, false);
for (Method method : methods) {
try {
mc.doWith(method);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
}
}
}
(v)创建AutowiredFieldElement对象,Field类型和Method类型的AutowiredFieldElement对象区别在于属性isField的值不同。
public AutowiredFieldElement(Field field, boolean required) {
super(field, null);
this.required = required;
}
public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {
super(method, pd);
this.required = required;
}
protected InjectedElement(Member member, @Nullable PropertyDescriptor pd) {
this.member = member;
// 是域还是方法
this.isField = (member instanceof Field);
this.pd = pd;
}
// Field和Method都是Member的实现
public final
class Field extends AccessibleObject implements Member {
……
}
public final class Method extends Executable {
}
public abstract class Executable extends AccessibleObject
implements Member, GenericDeclaration {
}
(iv)代码块五:inject(),属性注入
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
//element 分为FieldElement和MethodElement
element.inject(target, beanName, pvs);
}
}
}
a.Field类型的AutowiredFieldElement的注入
这个方法中有很多我们在byType中已经分析过的方法,resolveDependency()、registerDependentBeans(),通过Field获取属性描述器,根据field的Class类型去容器中找对应的实现类,如果resolveDependency()在field中找到多个(matchingBeans),不同于byType的是,当使用@Autowired进行依赖注入时descriptor.getDependencyName()为属性名称(field.getName()),matchingBeans.get(fieldName)返回符合规则的候选实例。推断出候选对象后维护依赖关系对应的集合。
这个方法还会创建缓存,不过是在只推断出一个候选对象的时候才会有缓存。而且这里缓存的只是属性的描述器desc和推断出来的autowiredBeanName,并没有将推断出来的候选对象实例加入缓存,这就意味着即使有缓存,还是要再执行esolveDependency()才能推断出最后注入的候选对象,只是缓存了某些中间变量的设置。
//Field属性注入
// AutowiredFieldElement.inject()
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
//cached的作用是什么
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
//核心方法
/**
* desc是这个field的信息,beanName为field对应的name
*/
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
//维护依赖关系
registerDependentBeans(beanName, autowiredBeanNames);
//只找到唯一的实现,如果是数组类型或集合类型,且找到多个实现,不会进行缓存
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
//设置缓存
// 这里缓存的只是属性的描述器desc和推断出来的autowiredBeanName,并没有将推断出来的候选对象实例加入缓存
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
//通过反射设置属性值
if (value != null) {
// 设置访问权限field.setAccessible(true);
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
b.Method类型的AutowiredFieldElement的注入。
与Field类型的AutowiredFieldElement的注入逻辑类似。
// AutowiredMethodElement.inject()
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
Object[] arguments;
if (this.cached) {
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
}
else {
int argumentCount = method.getParameterCount();
arguments = new Object[argumentCount];
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
// 当前被注入的特定依赖项的描述符
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
/**
* 解析出注入的属性值,byType源码部分已经分析了这个方法
*@see org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set, org.springframework.beans.TypeConverter)
*/
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
// 维护依赖关系集合,byType源码部分已经分析了这个方法
registerDependentBeans(beanName, autowiredBeans);
// 返回的候选beanName的大小与方法参数个数一致
// 如果方法参数是数组或集合类型且找到多个实现,不会进入这个方法
if (autowiredBeans.size() == argumentCount) {
Iterator<String> it = autowiredBeans.iterator();
Class<?>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
// beanName对应的bean实例的类型是否与paramTypes类型一致
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
// 放入缓存快照
// 这里缓存的只是属性的描述器desc和推断出来的autowiredBeanName,并没有将推断出来的候选对象实例加入缓存
// 所以拿到缓存后还需要执行resolveDependency()推断出最终注入的候选实例对象
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
// 设置缓存标识为true
this.cached = true;
}
}
}
if (arguments != null) {
try {
// 设置访问权限
ReflectionUtils.makeAccessible(method);
// 反射执行方法
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
不同于byType,属性注入方法 inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)中的参数pvs在Field类型和Method类型的注入中都没有用到。@Autowired依赖注入是通过Java反射(field.set(bean, value)/method.invoke(bean, arguments))实现的。
五、总结
Spring中的自动装配确实帮我们简化了一些属性的配置,但是对于简单类型,如String、int等基本数据类型,是无法使用自动装配的。同时在存在多个存在歧义的对象时,自动装配会返回不确定的结果,甚至会抛出异常。日常开发中,我们更多的是使用 @Autowired注解(或@Resource注解)进行依赖注入,这种方式即实现了自动装配的灵活性,也兼顾了手动装配的可预知性。
通过阅读源码发现:@Autowired注解(或@Resource注解)依赖注入是通过Java反射(field.set(bean, value)/method.invoke(bean, arguments))实现的,byName和byType是将推断出来的属性名称和属性对象添加到PropertyValues中,后续在封装BeanWrapper对象时通过Java内省机制完成属性注入的。