依赖注入
具体代码是在AbstractAutowireCapableBeanFactory
类的populateBean()
方法,此方法中主要做的事情如下:
- 实例化之后,调用
InstantiationAwareBeanPostProcessor
接口的postProcessAfterInstantiation
方法 - Spring早期通过BY_NAME或BY_TYPE两种方式,并利用set方法进行依赖注入
- 通过
InstantiationAwareBeanPostProcessor
接口的postProcessProperties()
方法进行依赖注入,典型的代表就是@Autowired
等注解的处理 - 将BeanDefinition中的PropertyValues覆盖
@Autowired
等注解的值
原始依赖注入方式
首先分析Spring早期的依赖注入
@Bean(autowire = Autowire.BY_NAME)
public UserService userService(){
return new UserService();
}
接下来就会遍历UserService中所有的set方法进行依赖注入。
对应的Spring源码是
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 必须是BY_NAME或BY_TYPE
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// MutablePropertyValues是PropertyValues具体的实现类
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 这里会根据我们的配置来分别调用不同的方法
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
接下来看autowireByName()
方法,主要过程就是先根据set方法找出所有的属性名,然后在遍历属性名集合,去单例池中找,再赋值给pvs变量
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 当前Bean中能进行自动注入的属性名,是根据setXXX()方法生成是属性名
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 遍历每个属性名,并去获取Bean对象,并设置到pvs中
for (String propertyName : propertyNames) {
// 要进行依赖注入的属性在当前容器中是否存在
if (containsBean(propertyName)) {
// 从容器中取出来,再存入pvs中
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
// 记录一下propertyName对应的Bean被beanName给依赖了
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
而autowireByType()
方法其实也类似,首先得到属性名集合,再遍历集合,然后得到方法形参的类型,根据resolveDependency()
找到bean对象,再存入pvs
注解方式
我们常用的方式是利用@Autowired等注解的方式实现依赖注入的,在Spring源码AbstractAutowireCapableBeanFactory
类的populateBean()
方法中对应的实现其实就是利用InstantiationAwareBeanPostProcessor
接口的postProcessProperties()
方法实现的
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// @Autowired注解 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
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;
}
@Autowired
和@Value
注解是通过AutowiredAnnotationBeanPostProcessor
类处理的
@Resource
注解是通过CommonAnnotationBeanPostProcessor
类处理的
实现看AutowiredAnnotationBeanPostProcessor
类的定义,它实现了初始化后置处理器以及BeanDefinition后置处理器两个接口,所以该类就会有下面两个方法
InstantiationAwareBeanPostProcessor
接口的postProcessProperties()
方法
MergedBeanDefinitionPostProcessor
接口的postProcessMergedBeanDefinition()
方法
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
...
}
根据我们对Bean生命周期的了解可以知道,postProcessMergedBeanDefinition()
方法先执行,postProcessProperties()
方法后执行
寻找注入点
我们可以先想一想如果要自己实现依赖注入应该要怎么做?首先就是找出类里面所有加了@Autowired注解的属性和Set方法,这个也称为注入点,然后在为这些注入点赋值。接下来看具体的实现,首先的BeanDefinition的后置处理器方法
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 根据类的class对象找到所有的注入点
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
先看findAutowiringMetadata()
方法逻辑
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// cacheKey其实就beanName
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 该类的所有注入点会缓存到injectionMetadataCache中
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)<