spring中BeanPostProcessor之四:AutowiredAnnotationBeanPostProcessor(01)


在《spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)》中分析了CommonAnnotationBeanPostProcessor類中的postProcessMergedBeanDefinition方法的作用,即是對類中的@Resources、@WebServiceRef、@EJB三個注解進行解析並緩存起來,以便后續執行postProcessProperties方法的時候用到緩存的信息。在spring啟動過程中還有一個和CommonAnnotationBeanPostProcessor類相似的bean后置處理器,該類就是AutowiredAnnotationBeanPostProcessor,該bean后置處理器的作用是處理@Autowired、@Value、@Inject注解。

一、概述

前面說到AutowiredAnnotationBeanPostProcessor類是解析@Autowired注解的,那么該注解的作用是什么那,是怎么定義的那

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

    /**
     * Declares whether the annotated dependency is required.
     * <p>Defaults to {@code true}.
     */
    boolean required() default true;

}

上面是該注解的定義,該注解的作用是自動注入,該注解是Spring提供的注解(@Resource、@WebServiceRef、@EJB均是java提供的)。

AutowriedAnnotationBeanPostProcessor要解析@Autowired注解那么按照前面分析的CommonAnnotationBeanPostProcessor和InitDestroyBeanPostProcessor兩個類,必須要先有要解析的類型,也就是初始化解析的類型,看AutoworedAnnotationBeanPostProcessor的構造方法,

@SuppressWarnings("unchecked")
    public AutowiredAnnotationBeanPostProcessor() {
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);
        try {
            this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                    ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
            logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }

上面是其默認的構造方法,可以看到向autowiredAnnotationTypes中加了三個注解:@Autowired、@Value、@Inject,其中@Inject是java中的注解,其余兩個均是Spring提供的注解。那么這里其實是說明AutowiredAnnotationBeanPostProcessor類是解析這三個注解的,我們繼續往下分析。

二、詳述

 1、方法概述

下面看AutoWiredAnnotationBeanPostProcessor類中的方法,

上面給出了AutoWiredAnnotationBeanPostProcessor類中的主要的方法,重點看postProcessMergedBeanDefinition和postProcessProperties方法,postProcessPropertyValue方法在前邊已經說過該方法已經廢棄了,調用的是postProcessProperties方法。

2、postProcessMergedBeanDefinition

該方法的作用是解析類中標記了@AutoWired、@Value、@Inject注解的屬性和方法,下面看具體的方法定義,

@Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }

2.1、findAutowiringMetadata

下面看findAutowiringMetadata方法

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); }
//查找目標類clazz中的標識了@AutoWired、@Value、@Inejct注解 metadata
= buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; }

從上面的代碼中可以看出最終是把標識了@AutoWired、@Value、@Inject注解的方法或字段信息封裝為Metadata然后放在了injectionMetadataCache中,重點看buildAutowiringMetadata方法,

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        /**autowiredAnnotationTypes中得值為
         * @AutoWired org.springframework.beans.factory.annotation.Autowired
         * @Value org.springframework.beans.factory.annotation.Value
         * @Inject javax.inject.Inject
         * 
         */
        
        if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
            return InjectionMetadata.EMPTY;
        }

        List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
        Class<?> targetClass = clazz;

        do {
            final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

            //判斷字段上是否存在autowiredAnnotationTypes中的注解
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
                MergedAnnotation<?> 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));
                }
            });

            //判斷方法上是否存在autowiredAnnotationTypes中的注解
            ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                    return;
                }
                MergedAnnotation<?> 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 InjectionMetadata.forElements(elements, clazz);
    }

該代碼比較多,主要是對目標類中的方法和字段信息進行了檢查,判斷是否標注了@AutoWired、@Value、@Inject三個注解,最后返回InjectionMetadata.forElements該方法是做什么的那,由於前邊生成的對象是elements的對象,看elements對象的類型,

List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();

是一個ArrayList類型,泛型是InjectionMetadata.InejctedElement,下面看該方法,

public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
        return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
    }

從上面的代碼可以看到,最終是new了一個InjectionMetadata的實例。最終buildAutowiringMetadata方法返回的是一個InjectionMetadata的實例。

buildAutowiringMetadata方法執行完以后,在findAutowiringMetadata方法中,把返回的InjectionMetadata實例放入了injectionMetadataCache中,最終返回一個InjectionMetadata實例。

2.2、checkConfigMembers

在postProcessMergedBeanDefinition方法中的第二行代碼即調用了checkConfigMembers方法

metadata.checkConfigMembers(beanDefinition);

該方法的定義如下,

public void checkConfigMembers(RootBeanDefinition beanDefinition) {
        Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
        for (InjectedElement element : this.injectedElements) {
            Member member = element.getMember();
            if (!beanDefinition.isExternallyManagedConfigMember(member)) {
                beanDefinition.registerExternallyManagedConfigMember(member);
                checkedElements.add(element);
                if (logger.isTraceEnabled()) {
                    logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
                }
            }
        }
        this.checkedElements = checkedElements;
    }

從上面的代碼中可以看出首先new了一個checkedElements,使用的是injectedElements的長度,injectedElements是什么那,怎么賦值的那。在buildAutowiringMetadata方法的最后調用了InectionMetadata.forElements方法,在該方法中最后生成了一個InjectionMetadata對象,傳入了elements對象,便是該對象。

checkConfiMembers方法主要是調用了beanDefintion.isExternallyManagedConfigMemgber方法,該方法暫時不討論。

 

3、postProcessProperties

上面分析了postProcessMergedBeanDefinition方法后,我們知道該方法的作用就是收集類中的標注了@AutoWired、@Value、@Inject注解的字段或方法,那么postProcessProperties方法便是在進行賦值的時候調用的,

//完成@AutoWired屬性的注入
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        //再次獲取了類中標注了@AutoWired、@Value、@Inject屬性的信息
        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;
    }

在該方法中又一次獲取了類中標注了@AutoWired、@Value、@Inject屬性的信息,重點是下面這行代碼,

//屬性注入
            metadata.inject(bean, beanName, pvs);

下面看inject方法,

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectedElement> checkedElements = this.checkedElements;
        //如果checkedElements為空,則取injectedElements
        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);
            }
        }
    }

上面在進行屬性注入的時候調用了element.inject方法,該方法在InjectionMetadata.InjectedElement類中,進去該方法看到如下,

/**
         * 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();
                }
            }
        }

看這方法的注釋,意思是需要覆蓋該方法,也就是說這里調用的不是上面的inject方法,在回到下面的代碼

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectedElement> checkedElements = this.checkedElements;
        //如果checkedElements為空,則取injectedElements
        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);
            }
        }
    }

遍歷elementsToIterate,通過調試我們看到這里的element是下面的類型

再來看AutowiredFieldElement是什么,

AutowiredFieldElement是AutowiredAnnotationBeanPostProcessor中的內部類,繼承了InjectionMetadata.InjectedElement類,上面提到了該方法,那么該類中肯定覆蓋了inject方法

@Override
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
            Object value;
            if (this.cached) {
                value = resolvedCachedArgument(beanName, this.cachedFieldValue);
            }
            else {
                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 {
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                }
                catch (BeansException ex) {
                    throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
                }
                synchronized (this) {
                    if (!this.cached) {
                        if (value != null || this.required) {
                            this.cachedFieldValue = desc;
                            registerDependentBeans(beanName, autowiredBeanNames);
                            if (autowiredBeanNames.size() == 1) {
                                String autowiredBeanName = autowiredBeanNames.iterator().next();
                                if (beanFactory.containsBean(autowiredBeanName) &&
                                        beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                    this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                            desc, autowiredBeanName, field.getType());
                                }
                            }
                        }
                        else {
                            this.cachedFieldValue = null;
                        }
                        this.cached = true;
                    }
                }
            }
            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);
            }
        }
    }

此方法的具體執行邏輯暫時不說。

三、使用場景

上面大體分析了AutowiredAnnotationBeanPostProcessor類中的postProcessMergedBeanDefinition和postProcessProperties兩個方法,了解了其作用及執行時機,文中遺留的問題后面會繼續分析。

 

有不當之處,歡迎指正,感謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM