常用的@Autowired
这个估计是使用spring最常用的注解了,往一个bean添加依赖,作用应该众所周知
@Value
@Value 一般用作配置类,比如:
@Value("${file.server.host}")
private String basicHost;
AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor 是解析这两个注解的关键
* @see Autowired
* @see Value
*/
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
}
可以看到这个类,继承了InstantiationAwareBeanPostProcessorAdapter实现了父类方法postProcessProperties。并且实现了MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition。这两个bean后置处理器再bean实例化,初始化过程都有有作用的,详情请见 tech.souyunku.com5efefb…
AutowiredAnnotationBeanPostProcessor实例化做了什么
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
.......省略添加 @Inject 的方法
}
实例化的时候往 autowiredAnnotationTypes 这个set集合放入 Autowired 和value这两个classs。
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//重要方法,往下走
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
//......校验获取缓存key,省略
//从缓存中获取 InjectionMetadata
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
//重复校验,从缓存取,省略
//重要,往下走就会解析
metadata = buildAutowiringMetadata(clazz);
//将获取到的metadata放到缓存中,让下次的后置处理器来取(postProcessProperties)
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//对属性的解析 遍历 autowiredAnnotationTypes(初始化的时候塞了三个注解进去)
//看是否这个类的属性有这三个注解,如果有就放到List中缓存下来
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//找属性是否有@Autowired @Value @Inject
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
//判断注解的 require 属性
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//.....上面是对属性的解析,下面是对方法的解析方法也可以@Autowire等注解
//大概意思差不多就省略,只是两个解析后的结果封装的对象不同
//属性:AutowiredFieldElement 方法:AutowiredMethodElement
//都是继承 InjectionMetadata.InjectedElement
}
while (targetClass != null && targetClass != Object.class);
//将解析完之后的elements(List) 放到 InjectionMetadata对象中,然后缓存到map中
return new InjectionMetadata(clazz, elements);
}
将解析出来之后的数据放到缓存之后,肯定有人取get缓存然后处理,如果了解bean的初始化就知道是哪个类的哪个方法去取这个缓存来解析的
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
这个方法也在spring的后置处理器中讲过了,主要是往bean中填充属性等等
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//调用上面的findAutowiringMetadata这个方法
//这个方法刚才也看了,一进去就会往缓存中取数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//调用inject,往下看inject做了什么
metadata.inject(bean, beanName, pvs);
}
return pvs;
}
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//............
//循环injectedElements 这个就是刚才解析完放到缓存的List
for (InjectedElement element : elementsToIterate) {
//往下看inject做了什么
element.inject(target, beanName, pvs);
}
}
}
以属性的解析为例
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
...........
//这个很重要,主要存放bean属性的一些描述
//比如属性的class,属性的名称,属性是否必须等等
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 {
//重要,从spring中获取依赖,其实这里才是依赖注入的核心
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
//....一些校验等省略
}
if (value != null) {
//调用反射,将属性设置进去,如果是方法其实也是调用反射
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//.......去掉对属性类型的判断,比如Optional,ObjectFactory,ObjectProvider等判断
//....
if (result == null) {
//真正干活的来了,往下走
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//........不影响主流程的 忽略
//这个可以看下,主要是判断依赖注入的属性是不是map,list,array等集合数组
//所以spring可以 @Autowire 一个List,map,当然前提是他们有多个实现
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//.....省略有关集合数组等处理,正常情况下很少用到
if (instanceCandidate instanceof Class) {
//最主要的来了
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
//.........
}
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);这句代码做了什么往下点进去
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
//其实就是调用beanFactory的getBean取获取实例
return beanFactory.getBean(beanName);
}
到这里算是解析完了,最后还是调用bean工厂的getBean获取到依赖的bean然后用反射注入进去
总结
AutowiredAnnotationBeanPostProcessor 主要是解决@Autowired 和 @Value注解的关键, AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor继承了InstantiationAwareBeanPostProcessorAdapter这两个,再bean的实例化过程分别先后被调用相应的方法 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition 是先调用解析出需要依赖注入的属性,放到缓存中。 InstantiationAwareBeanPostProcessorAdapte#postProcessProperties 后执行,这是后缓存中已经有了需要依赖注入的属性集合,直接拿,然后解析,最终通过bean工厂的getBean方法从spring容器中获取依赖,调用反射注入进去。