spring属性注入
spring的属性注入通过populateBean()方法实现。分为自动装配和手动装配
实例代码
package com.populate;
@Component
public class A {
@Autowired
I b;
@Autowired
List<I> m;
@Lazy
@Autowired
C c;
@PostConstruct
public void post(){
System.out.println("PostConstruct");
}
public void setXxxx(B b){
System.out.println("setXxx");
}
}
package com.populate;
@Component
public class B implements I {
}
package com.populate;
@Component
public class C implements I{
}
package com.populate;
@Component
public interface I {
}
package com.populate;
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
//beanDefinition.setAutowireMode(2); //当debug分析自动注入时打开
}
}
package com;
@Configuration
@ComponentScan("com.populate")
public class AppConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(ac.getBean(A.class));
}
}
调用链过程
AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#populateBean
postProcessAfterInstantiation
第五次后置处理器调用。判断是否需要属性注入
首先对所有的bean后置处理器进行遍历。对于符合InstantiationAwareBeanPostProcessor的调用postProcessAfterInstantiation方法。默认返回true。continueWithPropertyPopulation值默认是true将不会被修改
![](https://img.haomeiwen.com/i7310356/4a3b12207b233cfe.png)
postProcessPropertyValues
第六次后置处理器调用。对所有后置处理器进行遍历,属于InstantiationAwareBeanPostProcessor的调用postProcessPropertyValues方法。符合InstantiationAwareBeanPostProcessor类的:
1、ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
![](https://img.haomeiwen.com/i7310356/cd7c283c37de9528.png)
![](https://img.haomeiwen.com/i7310356/37f5584b35ed5f71.png)
2、CommonAnnotationBeanPostProcessor
![](https://img.haomeiwen.com/i7310356/7bde95fa8832c155.png)
3、AutowiredAnnotationBeanPostProcessor
4、RequiredAnnotationBeanPostProcessor
![](https://img.haomeiwen.com/i7310356/2fe4a54e4724ed26.png)
AutowiredAnnotationBeanPostProcessor
主要分析加了Autowired注解的如何进行属性填充的
postProcessPropertyValues
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
首先找到AutowiringMetadata,然后调用inject进行注入
![](https://img.haomeiwen.com/i7310356/48482998b935a23f.png)
findAutowiringMetadata
AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
经过第三次后置处理器调用。已经对注入点元数据放到injectionMetadataCache集合进行了缓存,所有到这里可以直接取出三个:
1、com.populate.I com.populate.A.b
2、java.util.List com.populate.A.m
3、com.populate.C com.populate.A.c
![](https://img.haomeiwen.com/i7310356/21ee4af3bb9f2764.png)
inject A.b属性
com.populate.I com.populate.A.b
InjectionMetadata#inject
对三个注入点数据进行遍历,依次调用inject方法。首先对com.populate.A.b的b属性调用
![](https://img.haomeiwen.com/i7310356/e681cf4652225a07.png)
inject
AutowiredFieldElement#inject
转换成field,组合成DependencyDescriptor依赖描述对象desc。从beanFactory获取依赖值
![](https://img.haomeiwen.com/i7310356/c3895066f27adbc2.png)
resolveDependency
DefaultListableBeanFactory#resolveDependency
在这里主要有两个步骤,是否加了@lazy注解用getLazyResolutionProxyIfNecessary处理,暂时先不管。先分析com.populate.I com.populate.A.b的b属性调用doResolveDependency方法
![](https://img.haomeiwen.com/i7310356/9a2d56c1f7639eb8.png)
doResolveDependency
DefaultListableBeanFactory#doResolveDependency
首先判断shortcut快捷依赖是否有值,第一次为null。然后得到b属性的依赖类型com.populate.I
![](https://img.haomeiwen.com/i7310356/35f0bb81fa94a1d9.png)
resolveMultipleBeans方法处理集合形式,实例代码中的java.util.List com.populate.A.m的m属性。此时分析com.populate.I com.populate.A.b的b属性调用findAutowireCandidates方法,返回结果放到matchingBeans集合
![](https://img.haomeiwen.com/i7310356/f43d7ae255d19f38.png)
findAutowireCandidates
DefaultListableBeanFactory#findAutowireCandidates
传入参数beanName=a,requiredType=com.populate.I ,descriptor是field b(查看debug数据)。在BeanFactory根据类型requiredType查找所有符合的beanName
![](https://img.haomeiwen.com/i7310356/28d228a3213c40f5.png)
beanNamesForTypeIncludingAncestors
BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class<?>, boolean, boolean)
![](https://img.haomeiwen.com/i7310356/39ebb2d101a7e959.png)
getBeanNamesForType
DefaultListableBeanFactory#getBeanNamesForType(Class<?>, boolean, boolean)
![](https://img.haomeiwen.com/i7310356/7dde4f8d936ae88f.png)
doGetBeanNamesForType
DefaultListableBeanFactory#doGetBeanNamesForType
遍历beanDefinitionNames
![](https://img.haomeiwen.com/i7310356/d0883ef26e2fc9bb.png)
对于匹配I类型的beanName放到result集合并返回
![](https://img.haomeiwen.com/i7310356/3c5555ab67da35f6.png)
findAutowireCandidates
DefaultListableBeanFactory#findAutowireCandidates
返回到得到candidateNames候选值。从beanFactory根据类型匹配得到的BeanName之后,首先判断resolvableDependencies集合中是否匹配当前类型I及其他的判断
![](https://img.haomeiwen.com/i7310356/3c22f70158b47f89.png)
遍历candidateNames候选值
![](https://img.haomeiwen.com/i7310356/ba0dbb205b05112c.png)
根据遍历candidateNames候选值得到类型并放到candidates集合
DefaultListableBeanFactory#addCandidateEntry
![](https://img.haomeiwen.com/i7310356/41490fa15f4960d8.png)
getType
AbstractBeanFactory#getType
获取candidate名字的类型
得到autowiredBeanName=b,从beanFactory的singletonObjects获取b的对象返回null
![](https://img.haomeiwen.com/i7310356/2b84af967cc873b2.png)
从mbd获取b的类型
![](https://img.haomeiwen.com/i7310356/19ee8f33efcf80ae.png)
AbstractAutowireCapableBeanFactory#predictBeanType
![](https://img.haomeiwen.com/i7310356/6f36b3bb63aeaf3f.png)
AbstractAutowireCapableBeanFactory#determineTargetType
![](https://img.haomeiwen.com/i7310356/1eccc088e1f1ba53.png)
遍历candidateNames完成,并把candidateName匹配的类型放到result集合并返回
doResolveDependency
DefaultListableBeanFactory#doResolveDependency
findAutowireCandidates方法得到匹配I接口的bean的matchingBeans含有两个(就是上步返回的result集合)。如果数量大于1,进入determineAutowireCandidate方法进一步处理
![](https://img.haomeiwen.com/i7310356/c93053e31e18cb73.png)
determineAutowireCandidate
DefaultListableBeanFactory#determineAutowireCandidate
首先判断是否符合primary或priority
![](https://img.haomeiwen.com/i7310356/633340edce7e56ba.png)
根据匹配的candidates集合的键(b和c)与加了Autowire属性名字(b)是否匹配是否相同,此时匹配b并返回
![](https://img.haomeiwen.com/i7310356/1dfb01428a84f8c6.png)
获取到instanceCandidate匹配的class类型
![](https://img.haomeiwen.com/i7310356/4e063de24e691180.png)
根据class类型从beanFactory获取对象
![](https://img.haomeiwen.com/i7310356/726fad8df9c5e6d5.png)
DependencyDescriptor#resolveCandidate
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
把得到的instanceCandidate赋值给result并返回,返回B对象
![](https://img.haomeiwen.com/i7310356/8c2a0f5a30f78a7c.png)
inject
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
创建ShortcutDependencyDescriptor快捷依赖描述赋值给cachedFieldValue
![](https://img.haomeiwen.com/i7310356/480cb4fd2812099c.png)
并把cached赋值为true
![](https://img.haomeiwen.com/i7310356/3c49ebef5cb64cb8.png)
通过field.set方法,注入属性值
![](https://img.haomeiwen.com/i7310356/366ab0be5f69c2f6.png)
此时便完成了加了@Autowired注解的属性b的注入。
在注入A.b属性过程中根据byType从Bean工厂获取找到了符合I接口的有两个。对于获取的candidateName从单例池获取如果返回null,则从相应的mdb中获取class类型,得到类型并封装成matchingBeans。然后再根据属性名称与符合接口的matchingBeans集合里面的值是否相匹配,最终找到一个。然后在匹配集合matchingBeans中得到类。
inject A.m属性
java.util.List com.populate.A.m
DefaultListableBeanFactory#doResolveDependency
![](https://img.haomeiwen.com/i7310356/afd41a09d7270d2c.png)
首先通过getDependencyType得到依赖的类型list
DefaultListableBeanFactory#resolveMultipleBeans
数组isArray
![](https://img.haomeiwen.com/i7310356/aab1ab8e8cdd18f2.png)
Collection类型且是接口isInterface
A.m属性符合条件,并获取符合注解类型的matchingBeans。经过TypeConverter转换并放到result中并返回
![](https://img.haomeiwen.com/i7310356/25d880113122cc07.png)
![](https://img.haomeiwen.com/i7310356/c4777646bc6aabae.png)
Map类型
![](https://img.haomeiwen.com/i7310356/d542d8257889972a.png)
此时再经过field.set便完成了加了@Autowired注解的属性b的注入。
inject A.c属性
对于属性加了@lazy的
com.populate.C com.populate.A.c
![](https://img.haomeiwen.com/i7310356/5a126904b4e43fa9.png)
ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary
![](https://img.haomeiwen.com/i7310356/c58f07f415cd758d.png)
ContextAnnotationAutowireCandidateResolver#buildLazyResolutionProxy
![](https://img.haomeiwen.com/i7310356/809ecb212f879155.png)
创建cglib代理并返回
![](https://img.haomeiwen.com/i7310356/b4a9fe91ca76e8be.png)
此时再经过field.set便完成了加了@Autowired注解的属性c的注入。
自动装配
仅分析自动装配模型是2(AUTOWIRE_BY_TYPE)通过类型装配过程
在分析之前,首先说明一下java的内省(Introspection)机制:
内省类提供了标准方法获取目标java Bean的属性、事件、方法。BeanInfo包括BeanDescriptor、EventSetDescriptor、PropertyDescriptor、MethodDescriptor等描述
populateBean
AbstractAutowireCapableBeanFactory#populateBean
首先根据装配类型AUTOWIRE_BY_TYPE,进入autowireByType(beanName, mbd, bw, newPvs)方法。在分析autowireByType调用链之前,先看看运行之后的结果是什么。
最终结果会得到MutablePropertyValues类型的属性值:其中 name是xxxx value是B。
然后debug查看这些结果是怎么获取的
![](https://img.haomeiwen.com/i7310356/32c2ce5168d97d6f.png)
autowireByType
AbstractAutowireCapableBeanFactory#autowireByType
经过unsatisfiedNonSimpleProperties方法会得到propertyNames数组值xxxx,所以重点分析这个方法
![](https://img.haomeiwen.com/i7310356/53008fb72a17af3e.png)
unsatisfiedNonSimpleProperties
AbstractAutowireCapableBeanFactory#unsatisfiedNonSimpleProperties
bw.getPropertyDescriptors()方法会得到PropertyDescriptor属性描述数组,其中包含xxxx,然后对pds进行遍历,是否符合WriteMethod方法,对于符合条件的PropertyDescriptor放到result集合并返回。所以需要进入分析getPropertyDescriptors这个方法。分析如何获取到的属性描述类PropertyDescriptor
![](https://img.haomeiwen.com/i7310356/58ced4cc059f1b06.png)
getPropertyDescriptors
BeanWrapperImpl#getPropertyDescriptors
![](https://img.haomeiwen.com/i7310356/10c01e26389c98b5.png)
getCachedIntrospectionResults
BeanWrapperImpl#getCachedIntrospectionResults
![](https://img.haomeiwen.com/i7310356/daed79a398dad7ff.png)
CachedIntrospectionResults#forClass
为给定的bean类创建CachedIntrospectionResults类
![](https://img.haomeiwen.com/i7310356/f903dc33e06fe78d.png)
CachedIntrospectionResults#CachedIntrospectionResults
![](https://img.haomeiwen.com/i7310356/93ad93bddd8991a5.png)
CachedIntrospectionResults#getBeanInfo(java.lang.Class<?>)
获取给定类的Beaninfo描述符
![](https://img.haomeiwen.com/i7310356/b9e78afaeecc5acc.png)
java.beans.Introspector#getBeanInfo(java.lang.Class<?>)
![](https://img.haomeiwen.com/i7310356/8b4c48f93e1a19d1.png)
java.beans.Introspector#getBeanInfo()
对java bean内省,获取它的所有属性、方法和事件
![](https://img.haomeiwen.com/i7310356/c6c8a47be50c2f02.png)
java.beans.Introspector#getTargetPropertyInfo
添加superBeanInfo父类的PropertyDescriptors到pdStore集合
![](https://img.haomeiwen.com/i7310356/6c74f7f36c07b819.png)
获取当前类的所有方法并遍历。如果方法isStatic则直接跳过
![](https://img.haomeiwen.com/i7310356/05cbae3e7aec7948.png)
获取当前方法名、参数类型、返回类型。如果方法名长度小于3且不是以is开头的直接跳过
![](https://img.haomeiwen.com/i7310356/5ff4dfccb09aceda.png)
如果参数数量是0,方法名以get开头的。创建PropertyDescriptor对象(如getAaa,则名字是aaa)
![](https://img.haomeiwen.com/i7310356/b1eac13d8495d05d.png)
参数个数是1,方法以set开头且返回类型是void 则创建PropertyDescriptor
![](https://img.haomeiwen.com/i7310356/49686e06491c9ce2.png)
参数个数是2,方法以set开头且第一个参数是Int类型,返回类型是void创建PropertyDescriptor 集合形式根据索引下标添加
![](https://img.haomeiwen.com/i7310356/7107de6489c64d59.png)
![](https://img.haomeiwen.com/i7310356/d7da2208ef1c1062.png)
最终返回到AbstractAutowireCapableBeanFactory#populateBean方法
![](https://img.haomeiwen.com/i7310356/fc5df48499370054.png)
AbstractAutowireCapableBeanFactory#applyPropertyValues
![](https://img.haomeiwen.com/i7310356/869b64887493585e.png)
![](https://img.haomeiwen.com/i7310356/cf1dddf383f17eba.png)
AbstractPropertyAccessor#setPropertyValues(PropertyValues)
![](https://img.haomeiwen.com/i7310356/86812fa03efd772c.png)
最终调用到writeMethod.invoke()调用方法
总结:
spring bean的属性注入分为手动注入和自动注入
手动注入:通过注解,典型案例是@Autowire、@Resource
通过调用相应的bean后置处理器的postProcessPropertyValues方法,通过field.set注入
自动装配:根据自动装配模型1(byName)、2(byType)
主要使用java的内省机制获取set开头方法,method.invoke调用