Bean的屬性裝配前1:MergedBeanDefinitionPostProcessor

接上文

繼續(xù)回到doCreateBean方法,經(jīng)過createBeanInstance(beanName, mbd, args),Spring已經(jīng)為我們創(chuàng)建好Bean實(shí)例,只是此時Bean尚未成熟,不能暴露給外部使用

再來到applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName),在這里Spring可以掃描每個類中那些屬性需要自動注入

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, 
        final @Nullable Object[] args) throws BeanCreationException {
    // ...
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                // 進(jìn)行一次后置處理器的處理,進(jìn)行掃描Bean類屬性是否使用了@Autowired等功能
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            } catch (Throwable ex) {
                // ...
            }
            mbd.postProcessed = true;
        }
    }
    // ...
    return exposedObject;
}

/**
 *  循環(huán)執(zhí)行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
 */
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, 
        Class<?> beanType, String beanName) {

    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }
}


擴(kuò)展:以AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor應(yīng)用為例,簡述MergedBeanDefinitionPostProcessor應(yīng)用

AutowiredAnnotationBeanPostProcessor

public class AutowiredAnnotationBeanPostProcessor 
        extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {

    private final Map<String, InjectionMetadata> injectionMetadataCache 
                                                        = new ConcurrentHashMap<>(256);

    // ...

    /**
     *  在構(gòu)造器中添加當(dāng)前后置處理器可以處理的注解:@Autowired、@Value、@Inject
     */
    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()));
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }

    /**
     *  通過postProcessMergedBeanDefinition查找當(dāng)前Bean需要注入的屬性
     */
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, 
            Class<?> beanType, String beanName) {
        // 查找當(dāng)前Bean定義中需要進(jìn)行Autowired操作的屬性
        // 生成一個當(dāng)前Bean注入屬性元數(shù)據(jù)對象
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        // 將需要注入的屬性元數(shù)據(jù)保存到當(dāng)前BeanDefinition中
        metadata.checkConfigMembers(beanDefinition);
    }

    /**
     *  查找類中需要注入的屬性元數(shù)據(jù)
     */
    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);
                    }
                    // 構(gòu)造當(dāng)前BeanDefinition需要進(jìn)行注入的屬性元數(shù)據(jù)
                    metadata = buildAutowiringMetadata(clazz);
                    // 緩存處理過的類屬性注入元數(shù)據(jù)
                    // 當(dāng)前后置處理器會處理所有Spring容器管理Bean的注入屬性元數(shù)據(jù)
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        return metadata;
    }

    /**
     *  實(shí)際查找類中需要注入的屬性元數(shù)據(jù)
     */
    private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
        Class<?> targetClass = clazz;
        // 循環(huán)這個類的所有屬性
        do {
            final LinkedList<InjectionMetadata.InjectedElement> currElements 
                                                                       = new LinkedList<>();

            ReflectionUtils.doWithLocalFields(targetClass, field -> {
                // 尋找含有在autowiredAnnotationTypes注解列表里面的屬性:
                // @Value、@Autowired、@Inject標(biāo)注的屬性
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    // 看到這里,就應(yīng)該明白為什么使用static修飾的屬性無法注入
                    // Spring并不將static屬性作為要自動注入的目標(biāo)?。。。?!
                    if (Modifier.isStatic(field.getModifiers())) {
                        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())) {
                        return;
                    }
                    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);
    }
    // ...
}

CommonAnnotationBeanPostProcessor

省略和AutowiredAnnotationBeanPostProcessor類似的處理流程,直接看它是怎么處理需要自動注入的屬性的,主要關(guān)注代碼中field.isAnnotationPresent是否含有注解的判斷

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
    LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
    Class<?> targetClass = clazz;

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

        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException(
                        "@WebServiceRef annotation is not supported on static fields");
                }
                currElements.add(new WebServiceRefElement(field, field, null));
            } else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException(
                        "@EJB annotation is not supported on static fields");
                }
                currElements.add(new EjbRefElement(field, field, null));
            } else if (field.isAnnotationPresent(Resource.class)) {
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException(
                        "@Resource annotation is not supported on static fields");
                }
                if (!ignoredResourceTypes.contains(field.getType().getName())) {
                    currElements.add(new ResourceElement(field, field, null));
                }
            }
        });

        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                if (webServiceRefClass != null 
                            && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException(
                            "@WebServiceRef annotation is not supported on static methods");
                    }
                    if (method.getParameterCount() != 1) {
                        throw new IllegalStateException(
                            "@WebServiceRef annotation requires a single-arg method: " 
                            + method);
                    }
                    PropertyDescriptor pd 
                                = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
                } else if (ejbRefClass != null 
                            && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException(
                            "@EJB annotation is not supported on static methods");
                    }
                    if (method.getParameterCount() != 1) {
                        throw new IllegalStateException(
                            "@EJB annotation requires a single-arg method: " + method);
                    }
                    PropertyDescriptor pd 
                                = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new EjbRefElement(method, bridgedMethod, pd));
                } else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException(
                            "@Resource annotation is not supported on static methods");
                    }
                    Class<?>[] paramTypes = method.getParameterTypes();
                    if (paramTypes.length != 1) {
                        throw new IllegalStateException(
                            "@Resource annotation requires a single-arg method: " + method);
                    }
                    if (!ignoredResourceTypes.contains(paramTypes[0].getName())) {
                        PropertyDescriptor pd 
                                    = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                        currElements.add(new ResourceElement(method, bridgedMethod, pd));
                    }
                }
            }
        });

        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    } while (targetClass != null && targetClass != Object.class);

    return new InjectionMetadata(clazz, elements);
}

小結(jié)

AutowiredAnnotationBeanPostProcessor會掃描Bean的類中是否使用了@Autowired@Value注解,掃描到的對象會封裝成一個InjectionMetadata對象,緩存到一個Map集合中,后續(xù)根據(jù)緩存信息進(jìn)行屬性填充;
CommonAnnotationBeanPostProcessor則會掃描Bean類中是否使用了@Resource等注解,同樣緩存起來等待后續(xù)進(jìn)行屬性填充。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容