@Autowired是属于Spring容器配置的一个注释,英文意思为自动装配
下面是@Autowired在Spring框架中的定义:
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
实现@Autowired注释功能的是处理器AutowiredAnnotationBeanPostProcessor位于org.springframework.beans.factory.annotation中。
预处理
AutowiredAnnotationBeanPostProcessor中的postProcessMergedBeanDefinition()方法先对其进行预处理,预处理代码如下:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);
metadata.checkConfigMembers(beanDefinition);
}
预处理的目的是找出所有注释了@Autowired的属性或方法,随后再进行注入。postProcessMergedBeanDefinition()方法通过调用findAutowiringMetadata()方法来获取所有的@Autowired属性和方法,findAutowiringMetadata()方法如下:
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();
InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized(this.injectionMetadataCache) {
metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = this.buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
indAutowiringMetadata()方法中的核心方法buildAutowiringMetadata()为:
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
List<InjectedElement> elements = new ArrayList();
Class targetClass = clazz;
do {
List<InjectedElement> currElements = new ArrayList();
ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
AnnotationAttributes ann = this.findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = this.determineRequiredStatus(ann);
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
AnnotationAttributes ann = this.findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0 && this.logger.isInfoEnabled()) {
this.logger.info("Autowired annotation should only be used on methods with parameters: " + method);
}
boolean required = this.determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
} while(targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
在buildAutowiringMetadata()方法中,做了如下几件事:
- 最外层的do...while..循环用于递归查找父类的@Autowired属性或方法;
- 通过反射的方式获取所有的属性并且循环验证每一个属性是否被@Autowired注解;
- 将查找到包含@Autowired注解的filed封装成AutowiredFieldElement,加入到列表中;
- 循环查找在方法上的注解;
- 将找到的方法封装成AutowiredMethodElement,并且加入列表。
执行注入
预处理结束后调用postProcessProperties()进行依赖注入:
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
return pvs;
} catch (BeanCreationException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
}
}
InjectionMetadata.inject()方法如下:
public class InjectionMetadata {
......
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
Collection<InjectionMetadata.InjectedElement> elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
InjectionMetadata.InjectedElement element;
if (!((Collection)elementsToIterate).isEmpty()) {
for(Iterator var6 = ((Collection)elementsToIterate).iterator(); var6.hasNext(); element.inject(target, beanName, pvs)) {
element = (InjectionMetadata.InjectedElement)var6.next();
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
}
}
}
......
}
利用for循环,遍历elements列表,进行注入。
在这里的代码当中我们也可以看到,是inject也使用了反射技术并且依然是分成字段和方法去处理的。在代码里面也调用了makeAccessible这样的可以称之为暴力破解的方法,但是反射技术本就是为框架等用途设计的,这也无可厚非。
总结
以上就是@Autowired注解实现逻辑的全部分析。结合源代码再看一遍的话,会更加清楚一点。下面是spring容器如何实现@AutoWired自动注入的过程的图: