https://www.jianshu.com/p/d511bcb502c3
大家用過spring的肯定都用過AutoWired註解,但是你想過自動注入的原理嗎,這次就來說下自動注入是怎麼實現的。在之前的spring的ioc容器啓動過程中,我們都知道,ioc容器的啓動是從AbstractApplicationContext的refresh方法開始的,在ioc容器啓動時會初始化加載的BeanPostProcessor,那麼BeanPostProcessor是什麼呢?BeanPostProcessor就是在bean初始化時操作的後置處理器,那麼這和自動注入有什麼關係呢?這就要從我們要說的AutowiredAnnotationBeanPostProcessor說起了。先來看下AutowiredAnnotationBeanPostProcessor的類的結構
AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor實現了BeanPostProcessor接口,當 Spring 容器啓動時,AutowiredAnnotationBeanPostProcessor 將掃描 Spring 容器中所有 Bean,當發現 Bean 中擁有@Autowired 註解時就找到和其匹配(默認按類型匹配)的 Bean,並注入到對應的地方中去。先來看下buildAutowiringMetadata方法
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);
}
buildAutowiringMetadata方法解析等待自動注入類的所有屬性。它通過分析所有字段和方法並初始化org.springframework.beans.factory.annotation.InjectionMetadata類的實例來實現。InjectionMetadata類包含要注入的元素的列表。注入是通過Java的 Reflection Field set方法或Method invoke方法完成的。此過程直接在AutowiredAnnotationBeanPostProcessor的方法中調用public void processInjection(Object bean) throws BeanCreationException。它將所有可注入的bean檢索爲InjectionMetadata實例,並調用它們的inject()方法。
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
InjectedElement的inject方法
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
AutowiredAnnotationBeanPostProcessor類中的另一個重要方法是findAutowiredAnnotation。它通過分析屬於一個字段或一個方法的所有註解來查找@Autowired註解。如果未找到@Autowired註解,則返回null,字段或方法也就視爲不可注入。
@Nullable
private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
if (attributes != null) {
return attributes;
}
}
}
return null;
}
至此,spring的自動注入就完成了。
AutowiredAnnotationBeanPostProcessor的分析就到這裏了。
作者:skyguard
鏈接:https://www.jianshu.com/p/d511bcb502c3
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。