前言
Autowired注解是spring提供自动装配功能的注解,通过这个注解,spring能够在bean的依赖注入时注入相应的bean属性。 作为Java开发者,每天都可能用到Autowire注解,理解这个注解的实现流程是很有必要的,本文将介绍@Autowired的工作原理。
spring通过一个AutowiredAnnotationBeanPostProcessor后置处理器来实现@Autowired的功能,这个后置处理器即实现了MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法功能,又实现了InstantiationAwareBeanPostProcessorAdapter后置处理器的postProcessProperties方法和postProcessPropertyValues。
原理分析
下面我们先分析这两个后置处理的提供的功能。
一、Autowired注解元信息解析过程:MergedBeanDefinitionPostProcessor
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/**
* 提供修改beandefinition的回调函数
* @see AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
/**
* 重置回调,可用于清理资源
* @see DefaultListableBeanFactory#resetBeanDefinition
*/
default void resetBeanDefinition(String beanName) {
}
}
既然MergedBeanDefinitionPostProcessor有修改beandefinition的能力,那么看下AutowiredAnnotationBeanPostProcessor是怎么运用这个能力的。
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
//需要处理的注解类型
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
//这里是注解和注解目标对应的对象类信息缓存,避免多次读取
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
/**
* 这里可以看出默认会处理@Autowired,@Value,@Inject注解
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
}
/**
* 实现MergedBeanDefinitionPostProcessor接口方法,提供修改beandefinition的能力
*/
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//查找当前bean类型里所有加了autowiredAnnotationTypes注解的属性元信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
//将这些元信息和beandefinition绑定
metadata.checkConfigMembers(beanDefinition);
}
@Override
public void resetBeanDefinition(String beanName) {
this.lookupMethodsChecked.remove(beanName);
this.injectionMetadataCache.remove(beanName);
}
}
findAutowiringMetadata方法就是查找bean类型里符合autowiredAnnotationTypes的元信息
//根据class信息查找属性或方法的自动装配元信息
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);
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;
}
//根据class信息查找自动装配注解元信息和目标属性和方法信息
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
//查找符合自动装配的属性注解元信息(属性对象)
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//查找符合自动装配的方法注解元信息(方法对象)
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes 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 new InjectionMetadata(clazz, elements);
}
上面的步骤通过解析得到了符合自动装配注解bean的属性对象和方法对象,并和bean的definition进行绑定。这就是AutowiredAnnotationBeanPostProcessor利用MergedBeanDefinitionPostProcessor扩展点实现的功能。
二、Autowired注解注入对象流程:InstantiationAwareBeanPostProcessorAdapter
上一步这里只是解析到了需要自动装配的属性,还没有注入相应对象。那么注入对象的过程由AutowiredAnnotationBeanPostProcessor实现了InstantiationAwareBeanPostProcessorAdapter的功能。
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
//处理属性的功能,即完整自动注入属性
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//查找自动装配元信息
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;
}
}
老铁,@Autowire的原理是不是被问到过?看了今天的文章你还有疑问吗,有没有豁然开朗的感觉?欢迎留言探讨😄