天天看點

看完讓你吊打面試官-@Autowired注解到底怎麼實作的?(下)4 源碼分析

4 源碼分析

通過org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor可以實作依賴自動注入

通過這個類來處理@Autowired @Value Spring

它也可以管理JSR-303的@Inject

  • AutowiredAnnotationBeanPostProcessor

    構造函數中定義要處理的注解
  • 看完讓你吊打面試官-@Autowired注解到底怎麼實作的?(下)4 源碼分析
  • 看完讓你吊打面試官-@Autowired注解到底怎麼實作的?(下)4 源碼分析
  • 之後,有幾種方法對@Autowired處理

第一個,private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz)解析等待自動注入類的所有屬性。它通過分析所有字段和方法并初始化org.springframework.beans.factory.annotation.InjectionMetadata類的執行個體來實作。

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
        Class<?> targetClass = clazz;
        do {
            final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
            //分析所有字段
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
              //findAutowiredAnnotation(field)此方法後面會解釋
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("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.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static methods: " + method);
                        }
                        return;
                    }
                    if (method.getParameterCount() == 0) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("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);
        //傳回一個InjectionMetadata初始化的對象執行個體
        return new InjectionMetadata(clazz, elements);
    }
...
  /**
     * 'Native' processing method for direct calls with an arbitrary target instance,
     * resolving all of its fields and methods which are annotated with {@code @Autowired}.
     * @param bean the target instance to process
     * @throws BeanCreationException if autowiring failed
     */
    public void processInjection(Object bean) throws BeanCreationException {
        Class<?> clazz = bean.getClass();
        InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
        try {
            metadata.inject(bean, null, null);
        }
        catch (BeanCreationException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    "Injection of autowired dependencies failed for class [" + clazz + "]", ex);
        }
    }
      

InjectionMetadata

類包含要注入的元素的清單

看完讓你吊打面試官-@Autowired注解到底怎麼實作的?(下)4 源碼分析

注入是通過Java的API Reflection (Field set(Object obj, Object value) 或Method invoke(Object obj,Object … args)方法完成的

此過程直接在AutowiredAnnotationBeanPostProcessor的方法中調用

public void processInjection(Object bean) throws BeanCreationException

它将所有可注入的bean檢索為InjectionMetadata執行個體,并調用它們的inject()方法

public class InjectionMetadata {
  ...
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()) {
            boolean debug = logger.isDebugEnabled();
            for (InjectedElement element : elementsToIterate) {
                if (debug) {
                    logger.debug("Processing injected element of bean '" + beanName + "': " + element);
                }
                //看下面靜态内部類的方法
                element.inject(target, beanName, pvs);
            }
        }
    }
  ...
    public static abstract class InjectedElement {
        protected final Member member;
        protected final boolean isField;
      ...
        /**
         * Either this or {@link #getResourceToInject} needs to be overridden.
         */
        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();
                }
            }
        }
      ...
    }
}
      

findAutowiredAnnotation(AccessibleObject ao)

分析屬于一個字段或一個方法的所有注解來查找@Autowired注解。如果未找到@Autowired注解,則傳回null,字段或方法也就視為不可注入。

看完讓你吊打面試官-@Autowired注解到底怎麼實作的?(下)4 源碼分析