Springの展開点BenPostProcessorから見たSpring作成Beanの流れ

22618 ワード

一.BenPostProcessorとは何ですか?
public interface BeanPostProcessor {

    /**
     * Apply this BeanPostProcessor to the given new bean instance before any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * Apply this BeanPostProcessor to the given new bean instance after any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * 

In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding {@code bean instanceof FactoryBean} checks. *

This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }

BenPostProcessorはSpring容器の一つの拡張点であり、カスタムの実用化、初期化、依存組立、依存検査などの流れを行うことができます.すなわち、デフォルトの実例化をカバーすることができます.初期化、依存注入、依存検査などの流れを強化することもできます.
e.g. checking for marker interfaces or wrapping them with proxies.
大体の意味は、それぞれの識別インターフェースがいくつかのカスタム機能の実装を完了するかを確認することができます.
BeanPostProcessorは全部で二つの方法があります.postProcess BeforeInitiazationとpostProcess After Initializationと、この二つの方法は何のSpring実行プロセスの中でどのステップで実行されますか?今のところSpringはどのような実現を提供していますか?
Springはまた、BeanPostProcessorのいくつかの他のインターフェースを提供して、インスタンス化以外の他の機能を完成させて、後で詳しく紹介します.
二.SpringソースでBenPostProcessorの役割を見ます.
AbstractAplicationContect内部ではDefault Listable BeanFactoryを使用し、Default Listable BeanFactoryはAbstractoryを継承していますので、ここでAbstract AutowireCable Beable Factoryを分析すればいいです.
AbstractAutowireCapable BeanFactoryでbeanを作成する入り口はcreateBean方法です.
@Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;
        //1.  bean class
        Class> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // 2.       
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            //3.    BeanPostProcessor       (  InstantiationAwareBeanPostProcessor          )
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                //4.               bean      ,      bean,        
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }
        //5.   Spring      bean     
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
AbstractAutowireCable BeanFactoryのresoveBefore Instantiationの方法:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    //3.1   InstantiationAwareBeanPostProcessor postProcessBeforeInstantiation      
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        //3.2   3.1   bean     ,  InstantiationAwareBeanPostProcessor postProcessAfterInitialization     ,         ,   3     
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }
上記のコードにより、カスタマイズされた例示的な前処理(カスタマイズされた例示的なbean、例えば、対応するプロキシオブジェクトを作成する)と後処理(例えば、カスタマイズされた実用化されたbeanの依存組立)が行われる.
AbstractAutowireCapable BeanFactoryのdoCreateBenメソッドコードは以下の通りです.
//         bean      
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        // 6.  BeanWrapper   Bean   
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
        mbd.resolvedTargetType = beanType;

        // Allow post-processors to modify the merged bean definition.
        //7、  MergedBeanDefinitionPostProcessor postProcessMergedBeanDefinition  (        BeanDefination)
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        // 8.      Bean  ,    setter           
        //     bean           
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            //        bean(       )
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            //         bean(       ,        )   singletonFactory 
            addSingletonFactory(beanName, new ObjectFactory() {
                @Override
                public Object getObject() throws BeansException {
                    //    SmartInstantiationAwareBeanPostProcessor getEarlyBeanReference         Bean(             )
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //9.     bean   
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                //10.         bean   
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        if (earlySingletonExposure) {
           //11.     bean        ,   getSingleton    bean
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                   
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            //12.    bean     
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }
AbstractAutowireCable BeanFactoryのpoputlateBeanメソッドコードは以下の通りです.
//9.  bean
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();

        if (bw == null) {
            if (!pvs.isEmpty()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        boolean continueWithPropertyPopulation = true;
        //9.1   InstantiationAwareBeanPostProcessor            ( @Autowired   )  
        //  InstantiationAwareBeanPostProcessor postProcessAfterInstantiation      
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }

        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            //9.2   BeanName  BeanType       
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }
        
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
        //9.3   InstantiationAwareBeanPostProcessor postProcessPropertyValues~~~~ 
        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                //9.4       
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }
        //9.5       
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
AbstractAutowireCable BeanFactoryのinitializaBenメソッドコードは以下の通りです.
//10          bean     
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        //10.1   Aware    (BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }
        
        Object wrappedBean = bean;
        //10.2   BeanPostProcessor    postProcessBeforeInitialization  bean       
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
       
        //10.3        (1   InitializingBean afterPropertiesSet  2       init-method)
        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        //10.4   BeanPostProcessor    postProcessAfterInitialization       Bean  
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }
三.まとめ
Springのソースコードの解読を通して、皆様はBeanPostProcessorというインターフェースに対して一定の理解ができたと信じています.ビーンPostProcessorが基本的にSpringを貫いてビーンを創建するライフサイクルを見られます.次にビーンPostProcessorのいくつかの拡張点をまとめます.
2.mbd.prepare MethodOverrides()、準備と検証構成の方法注入、もし検証が失敗したらBeanDefinitionValidation Exceptionを抛り出す;
3 Object bean=reolveBefore Instantiation;最初のBenPostProcessor拡張点は、ここではInstantiationAwareBenPostProcessorタイプのBenPostProcessorBeanのみ実行します.3.1 bean=appyBenPostProcessors Before Instantiation(mbd.get BenClass()、beanName)、InstantiationAwareBeabenPostProcessorの実際化の前処理方法postProcess Before Instantiation(作成代理などのカスタムの実用化)を実行する.3.2 bean=appyBenPostProcessors AfterInitialization(bean、beanName);InstantiationAwareBeanPostProcessorの実装を実行した後処理フィードバック方法postProcess After Initializationは、3.1で戻るBeanがnullでない場合に実行されます.
4.3つの拡張点から戻ってきたbeanが空でない場合、直接にbeanに戻り、後続のフローは実行する必要がない.
5.Object beanInstance=doCreateBean(beanName,mbd,args)は、springの作成beanの例の流れを実行します.
6 createBeanInstance(beanName、mbd、args)は、Beanを実行します.6.1 instantiateUsingFactory Method工場の方法の実例化;6.2コンストラクタの実装;6.2.1前に既に解析済みのコンストラクタの場合.6.2.5.1 autwireConstructor:aut wireConstructorを起動する実務例があります.6.2.1.2 instantiateBen:無参呼出instantiateBeanの実証化;6.2.2以前に解析したコンストラクタがない場合:6.2.1 SmartInstantiationAwareBenPostProcessorのdetermine CadidateContstructorフィードバック方式でコンストラクタを解析し、第二のBenPostProcessorの拡張点を通じて、最初の解析成功(リターン値はnullではない)のコンスセットを返します.AutowiredAnnotationBeanPostProcessorのように自動スキャンを@Autowired/@Value注解するコンストラクタを実現してコンストラクタ注入を完成することができます.6.2.2、autwireConstructor:もし(6.2.1がnullではなく、かつコンストラクタがある場合、autwireContstructorを呼び出して実例化する;6.2.2、instantiateBen:さもなければ、無参与コンストラクタを呼び出して実例化する;
7 appyMergedBenDefinitionPostProcessors;第三のBenPostProcessor拡張点、Bern定義の合併を実行し、MergdBenDefinitionPostProcessorのpostProcessorのpostProtocessionメソッドを実行して、beanを定義します.
8
addSingletonFactory(beanName, new ObjectFactory() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
一例のBean引用を早期に暴露し、setter注入方式の循環参照を可能にする.8.1、SmartInstantiationAwareBenPostProcessorのget EarlyBenReference、第四のBenPostProcessor拡張点は、サイクル依存がある場合、このフィードバック方法で早期露出のBeanインスタンスを取得する.
9 populteBean(beanName,mbd,instance Wrapper)装着ビーンは9.1 InstantiationAwareBenPostProcessorのpostProcess After Instantiationに依存しています.第5のBenPostProcessor拡張点は、実際のBean以降、他のすべての組立ロジックの前に実行されます.もしfalseが他のInstantiationAwareBeable PostProtocestorsiossorのpostration 9.2を阻止するなら、Protocestorsions.Protocestors.Protocestors.Protocestorsions.Protocestors.Awaresor.のpostアウトレットwireByName、atowireByType:名前と種類によって自動組立を行います.9.3 InstantiationAwareBeabinPostProcessorのpostProtocestyValues:第六のBeanPostProcessor拡張点によって、AutowiredAntonPoint Point Point Point Protocestorsionators@注入など、他のカスタムのいくつかの依存注入を完了します.の注入、Persistence AnnotationBeanPostProcessor執行@PersistencContectなどのJPA注解の注入、RequiredAnnotationBeanPostProcessor執行@Required注解の検査など、9.4 check Dependencies:依存検査、9.5 appyPropertyVales:アプリケーションの明確な入力属性.
10 exposedObject=initializaBen(beanName、exposedObject、mbd);初期化Beanフローを実行する;10.1 invoke AwareMethods(BenNameAware、BenClass Loader Aware、BenFactoryAware):いくつかのAwareの識別インターフェースを呼び出してビーンName、BeanFactoryのように注入します.10.2ビーンPostProcessorのpostProcess Before Initialization:7番目の拡張点は、呼び出しの初期化前にいくつかのカスタマイズされた初期化タスクを完成します.例えば、BeabinValidation PostProcessorはJSR-33@Valid注釈Bernを完成します.いくつかのAwareインターフェースの注入を完了しました.(Evironment Aware、Resource Loader Aware、Appliation Contact Aware)の戻り値は元のBenオブジェクトに置き換えられます.10.3 invokeInitMethods:初期化方法を呼び出します.10.3.1 Initializing BeaftのafterPropertist呼び出し:Initializing Beat Beatの設定によってカスタマイズされたサービスを呼び出します.thod;10.3.3 BeanPostProcessorのpostProcess After Initialization:8番目の拡張点AsppectJAwareAdvisor AutoxyCreator(xmlスタイルを完成させたAOP配置()のターゲットOPはAOPエージェントに包装されます.その戻り値は元のBeanオブジェクトに代わる.
11 earlySingleExposureであれば、getSingle方法を呼び出してビーコンのインスタンスを取得し、earlySingleExposure=(mbd.isSingleton()&&&this.allowCircurcarraferences&&&&&isSingleton CurrenctlyInCreation)は単一の例Beaningであり、かつデフォルトの場合は参照を作成してください.Object Factory.getObject()の呼出により、【8.1】におけるgetEarlyBenReferenceを通じて関連Beanを取得する.
12 register Dispopsable BenIfNecessary:BeanName、bean、mbdを登録するBeanの廃棄方法(プロトタイプ以外のBeanのみ登録可能):12.1単一例Beanの破壊プロセス12.1.1 Destruction AwareBeabenPostProcessorのpostProcess Before Destruction:9番目の拡張点、例えば:Init Destruction PostProcessor完成@Processorの廃棄方法登録と呼び出し、12.1.2 Discposable Beable Bernのdestration登録によってDiscoble/strationを呼び出す.ethod:XMLで指定されたdestroy-method廃棄方法を登録/呼び出します.12.1.2 Scopeのregister Destruction Callback:カスタムScopeを登録する廃棄フィードバック方法、例えばRequest Scape、Session Scapeなどです.その流れは【12.1の例Benの破壊プロセスと同じです.】
13、このBeanを実装し、注入に依存し、初期化したら、作成したbeanに戻ることができます.
これから分かるように、BenPostProcessorはこのインターフェースはSpring作成のシングル・インスタンスbeanの全体の過程を貫いています.開発過程において、オーダー化されたBenPostProestorによってbeanに対する修正を実現することができます.
このブログはhttps://www.iteye.com/topic/1122937