一篇文章讓你徹底搞懂Bean后置處理器及執(zhí)行時(shí)機(jī)

Bean生命周期涉及到的所有后置處理器及其執(zhí)行時(shí)機(jī)

看了本篇文章,你會(huì)有如下收獲

  1. 了解Bean生命周期流程
  2. 清楚有哪些后置處理器,及其在bean生命周期他們的執(zhí)行時(shí)機(jī)
  3. "實(shí)誠(chéng)"動(dòng)態(tài)debug gif
香蕉君圖片.jpg
  1. 看到滿滿的干貨,然后才能和面試官對(duì)線
image

要想看懂這篇文章,你應(yīng)該大致了解Spring的大致執(zhí)行流程,不過不了解的小伙伴別擔(dān)心,看看下面這段話

對(duì)下面流程不太熟悉的小伙伴也不需要擔(dān)心,大概了解就行

[圖片上傳失敗...(image-485ddf-1598633659159)]](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f3f13ff5e57945059002d0762cab067b~tplv-k3u1fbpfcp-zoom-1.image)

執(zhí)行流程里面的 postProcessor 主要是用來在某個(gè) 生命周期 執(zhí)行的時(shí)機(jī)點(diǎn) 調(diào)用而已

我都說到這個(gè)份兒上了,童鞋們最好都跟著Debug一下噢

言歸正傳 有個(gè)大前提:這里討論的是,在容器refresh末尾的時(shí)候,需要完成Bean工廠初始化回調(diào)(finishBeanFactoryInitialization, 在回調(diào)的最后會(huì)預(yù)先加載Bean(preInstantiateSingletons),從而調(diào)用 getBean的邏輯來完成初始化

重要的話說n次 最好跟著Debug噢,就拿你自己的web項(xiàng)目 debug也行

想下載源碼寫 test 的童靴,如果不會(huì)請(qǐng)?jiān)谙旅嬖u(píng)論區(qū)告訴我,我會(huì)補(bǔ)上Spring源碼搭建的教材噢!

如果還嫌麻煩,我可以把我搭建好的項(xiàng)目傳到gitee或者github,大家拉下來就能用了。

好,鋪墊到這兒,我們開始吧

一、接管bean創(chuàng)建邏輯,返回自定義bean

從getBean流程開始,當(dāng)bean創(chuàng)建的時(shí)候需要提前解析這個(gè)beanclass

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    // 如果這個(gè)bean沒有被解析過,這里第一次進(jìn)來肯定沒解析過
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        // 重要?。。『铣深愔R(shí),不想看這一大段文字,可以直接跳過,到下面if語句中
        // 這里的Synthetic指的是這個(gè)類是不是合成類,比如當(dāng)這個(gè)類有個(gè)內(nèi)部類的時(shí)候,這個(gè)類不能訪問到內(nèi)部類的私有變量
        // 但是這里jvm想要支持,怎么辦呢?
        // 所以它采取了一種策略,創(chuàng)建一個(gè)新的類出來,合成這個(gè)類和內(nèi)部類,使程序員在使用的時(shí)候看起來,可以直接訪問內(nèi)部類,這里不展開了
        // 感興趣的兄dei可以自己寫個(gè)類,看看class文件,會(huì)多出來一個(gè) xxx1.class
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            // 看到這兒,從方法名就可以初步猜測(cè)這里是推斷出class對(duì)象的
            // 但是他是怎么推斷出來的呢,emmmmm,嘿嘿,這里挖個(gè)坑,后面講
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 這里開始正式調(diào)用后置處理器,系統(tǒng)內(nèi)置的后置處理器啥都沒干
                // 除非你自己寫了個(gè)后置處理器,看下個(gè)代碼框
                // 而且你這個(gè)后置處理器提前給別人返回了一個(gè)bean,那么就會(huì)直接進(jìn)入下面的判斷完成初始化,直接結(jié)束
                // 如果你的公司想要自己去實(shí)現(xiàn)bean的初始化流程,那么就應(yīng)該在這里實(shí)現(xiàn)
                // 之后Spring就會(huì)直接返回你給的這個(gè)對(duì)象,如下所示
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    // 執(zhí)行后置處理,不同時(shí)機(jī)
                    // 下面有自定義的例子,gif演示
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}
自定義解析bean

[圖片上傳失敗...(image-382692-1598633659159)]](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/443aec3ebb5c476382e55f3af28e46c4~tplv-k3u1fbpfcp-zoom-1.image)

  • 值得一提的是,除了我們自己可以在這里添加自定義bean返回,如果我們開啟了自動(dòng)代理,Spring也會(huì)把我們自定義的bean進(jìn)行代理,感興趣的童鞋可以 在配置類上加個(gè) @EnableAspectJAutoProxy,寫個(gè)Aspect切面指定到我們的A類試試

二、自行推斷構(gòu)造方法

我們繼續(xù)去看第二個(gè)bean生命周期的執(zhí)行時(shí)機(jī),接下來,Spring就會(huì)去創(chuàng)建bean,那么問題來了,要?jiǎng)?chuàng)建一個(gè)bean,首先創(chuàng)建它的對(duì)象,如何創(chuàng)建對(duì)象?通過構(gòu)造方法 反射創(chuàng)建?沒錯(cuò),但如果你提供了多個(gè)構(gòu)造方法,我怎么知道要用哪個(gè)構(gòu)造方法創(chuàng)建呢(下節(jié)詳解,這里大概知道就行)Spring自己對(duì)構(gòu)造方法做了推斷,而推斷邏輯則是放在了 AutowiredAnnotationBeanPostProcessor 中去推斷

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
        throws BeansException {

    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            // 可以自己去實(shí)現(xiàn)SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors
            // 從而實(shí)現(xiàn)覆蓋 AutowiredAnnotationBeanPostProcessor 完成自定義
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
                if (ctors != null) {
                    return ctors;
                }
            }
        }
    }
    return null;
}

Spring 通過 AutowiredAnnotationBeanPostProcessor 實(shí)現(xiàn)的 推斷構(gòu)造方法,我們挖個(gè)坑,放到下篇專門講解推斷構(gòu)造方法講。

來來來,干了這一杯,還有··

對(duì)不起串臺(tái)了

來來來,我們自己寫個(gè)超簡(jiǎn)單的自定義后置處理器實(shí)現(xiàn)推斷構(gòu)造方法,去覆蓋Spring自己的推斷方法

image
@Component
public class CustomSmartInstantiationawareBPP implements SmartInstantiationAwareBeanPostProcessor {
    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("自己來推斷構(gòu)造方法");
        return beanClass.getDeclaredConstructors();
    }
}

結(jié)果:


getBean在解析bean之前返回bean自定義

可以看到創(chuàng)建所有bean的時(shí)候都被我們自定義的替換了

三、合并bean

首先我們來搞清楚一件事,什么是合并bean,在Spring中存在 三個(gè)BeanDefinition

  1. RootBeanDefinition 父BD
  2. ChildBeanDefinition 子BD
  3. GenericBeanDefinition 既可作用于父BD,又可是于子BD

現(xiàn)在有這么個(gè)情況,和java繼承思想類似,當(dāng)某個(gè)子BD繼承了父BD,在使用時(shí)可以通過子BD操作父類屬性(子類繼承父類)。
所以必須要合并一下BD,讓子類也有父類的屬性

父子BD解釋通了。那為什么不直接用GenericBD,或許是歷史遺留原因,現(xiàn)在的版本必須向前兼容,故而必須保留。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {

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

    // Allow post-processors to modify the merged bean definition.
    // 這里已經(jīng)寫得很清楚了,允許后置處理器去修改合并bean,我們來看看到底是哪個(gè)beanPostProcessor完成合并bean的呢?
    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;
        }
    }

    ·······
}

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);
        }
    }
}

CommonAnnotationBeanPostProcessor中,主要找 生命周期PostConstruct和PreDestroy切入點(diǎn)和資源切入@Resource xml的WebServiceRef 和 EJB

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    // 遍歷所有方法,找到所有 @PostConstruct 和 @PreDestroy 注解的方法 并把他們放到 bd 中 把他們放入 bd 的 checkedInitMethods 和 checkedDestroyMethods屬性中
    // 這里是調(diào)用了父類 “InitDestroyAnnotationBeanPostProcessor” 的方法
    super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    // 遍歷所有字段和方法,找到所有 @Resource 和 javax.xml.ws.WebServiceRef 和 javax.ejb.EJB 把他們放入 bd 的 checkedElements屬性中
    InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

AutowiredAnnotationBeanPostProcessor中,主要找 所有帶了 @Autowired的屬性和方法 (static無論方法屬性都不行)

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    // 找到所有有 @Autowired 的字段和注解放入 bd 的 checkedElements中
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

接下來,我們自己實(shí)現(xiàn)一個(gè)后置處理器,來找一個(gè)我們自己定義的注解,并把它也存到bd中

@Component
public class CustomMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
    // 模擬autowired注解解析流程
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        // 第一步先找到注解,封裝信息
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        // 第二步將注解信息注入 bd中
        metadata.checkConfigMembers(beanDefinition);
    }

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

    // 搞個(gè)和autowired類似的
    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);
                    }
                    metadata = buildAutowiringMetadata(clazz);
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        return metadata;
    }

    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 -> {
                if (field.isAnnotationPresent(ZWL.class)) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        return;
                    }
                    boolean required = field.getAnnotation(ZWL.class).required();
                    String requiredStr = required? "必輸":"非必輸";
                    // 用來保存 注解信息,這樣下次需要去注入時(shí),再通過該element注入就好
                    System.out.println("找到一個(gè)ZWL注解,在" + clazz.getSimpleName() + "類中,是" + requiredStr + "的");
                    currElements.add(new ZWLFieldElement(field, required));
                }
            });

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

        // 返回封裝后解析到的信息,用InjectionMetadata統(tǒng)一處理
        return new InjectionMetadata(clazz, elements);
    }

    private class ZWLFieldElement extends InjectionMetadata.InjectedElement {

        private final boolean required;

        private volatile boolean cached = false;

        @Nullable
        private volatile Object cachedFieldValue;

        public ZWLFieldElement(Field field, boolean required) {
            super(field, null);
            this.required = required;
        }

        @Override
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            // 注入bean
        }
    }
}

下面是良心的debug gif

image

四、提前使用工廠暴露代理對(duì)象

就如我們?cè)谏弦黄恼拢h(huán)依賴提到的,傳送門 ,在過程 A->B->A 給B注入A對(duì)象時(shí),如果A已經(jīng)被代理,那么必須給他注入一個(gè)代理對(duì)象才行,所以這個(gè)地方就是要通過工廠來生產(chǎn)了,而這個(gè)工廠的運(yùn)作方式,就是通過后置處理器返回的代理對(duì)象

上代碼,一清二楚

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 調(diào)用工廠方法生產(chǎn)
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

// 工廠方法
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                // 這么多后置處理器中有AnnotationAwareAspectJAutoProxyCreator 的 getEarlyBeanReference方法 創(chuàng)建了一個(gè)代理對(duì)象
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
    }
    return exposedObject;
}


正經(jīng)的分割線,預(yù)警!接下來的兩個(gè)后置處理器執(zhí)行時(shí)機(jī),是在注入屬性時(shí)執(zhí)行的


五、在bean注入屬性前,可以對(duì)bean做一些判斷修改,也可以直接中斷bean屬性注入(判斷是否需要繼續(xù)注入屬性)

// 在這里 Spring內(nèi)置的beanPostProcessor 什么事也沒干
// 所以只能我們自定義一個(gè)
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;
            }
        }
    }
}

// 來看看我們的自定義的例子,這里復(fù)用了之前的 CustomInstantiationAwareBPP
@Component
public class CustomInstantiationAwareBPP implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    Object result = null;
    if (beanName.equals("A")) {
        System.out.println("在初始化之前來整一個(gè)A");
        result = new ObjectA();
    }
    // 避免返回自定義對(duì)象,結(jié)束創(chuàng)建bean
    // return result;
    return null;
}

// 新的在這里?。?!
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    System.out.println("在屬性真正注入之前對(duì)" + beanName + "bean做些小動(dòng)作");
    // 是否繼續(xù)注入屬性,true則繼續(xù)
    return true;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (beanName.equals("A")) {
        System.out.println("A已經(jīng)整完了,好了,拿走吧");
    }
    return bean;
}
}

執(zhí)行的結(jié)果當(dāng)然就是打印出來了這句話

image

六、屬性注入

后置處理器的執(zhí)行點(diǎn)

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
    if (pvs == null) {
        pvs = mbd.getPropertyValues();
    }
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 修改bean的propertyValues
            PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                // 改方法已經(jīng)遺棄不建議使用
                pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
}

這里 CommonAnnotationBeanPostProcessor 會(huì)去注入之前提到過的 @Resource、WebServiceRef、EJB的屬性或者調(diào)用方法 設(shè)置值

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 還是和前面合并bean的功能一樣,查找@Resource等信息,如果之前有解析過,那么這里就不會(huì)解析了,直接拿出緩存中的值
    InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    try {
        // 上次是放到了將這些屬性注入到了BD中,這次是注入到Bean中
        metadata.inject(bean, beanName, pvs);
    } catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    }
    return pvs;
}

同樣的AutowiredAnnotationBeanPostProcessor 也是在這里完成屬性注入的,這里的 代碼邏輯就是找到 @Autowired 的屬性或方法 然后查找它合適的值然后注入,至于如何查找值,這個(gè)知識(shí)點(diǎn)下篇文章詳解

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    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;
}

最后照例,我們自己的 后置處理器,還是沿用之前的 CustomInstantiationAwareBPP

@Component
public class CustomInstantiationAwareBPP implements InstantiationAwareBeanPostProcessor {

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    Object result = null;
    if (beanName.equals("A")) {
        System.out.println("在初始化之前來整一個(gè)A");
        result = new ObjectA();
    }
    // 避免返回自定義對(duì)象,結(jié)束創(chuàng)建bean
    // return result;
    return null;
}

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    System.out.println("在屬性真正注入之前對(duì)" + beanName + "bean做些小動(dòng)作");
    // 是否繼續(xù)注入屬性,true則繼續(xù)
    return true;
}

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    System.out.println("對(duì)bean的PropertyValues 做修改,然后注入對(duì)應(yīng)屬性");
    return pvs;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (beanName.equals("A")) {
        System.out.println("A已經(jīng)整完了,好了,拿走吧");
    }
    return bean;
}
}

又到了畫分割線的季節(jié),下面才是猛男該看的東西

多圖預(yù)警?。?!


image
image
image
image

也就一般這么猛,言歸正傳,我們繼續(xù)

接下來就是在bean完成屬性注入后,對(duì)bean進(jìn)行初始化的執(zhí)行時(shí)機(jī)

七、在初始化前,調(diào)用各種aware

首先來看下初始化整體的調(diào)用邏輯

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 調(diào)用 bean 的aware類型的方法
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    // 在初始化之前調(diào)用
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 調(diào)用實(shí)現(xiàn)的初始化的方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }

    // 在初始化之后調(diào)用
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

初始化之前的切入點(diǎn)

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

首先看 ApplicationContextAwareProcessor 主要是去觸發(fā)一些實(shí)現(xiàn)了環(huán)境事件監(jiān)聽資源load``信息發(fā)布等等事件接口

@Override
@Nullable
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
    AccessControlContext acc = null;

    if (System.getSecurityManager() != null &&
            (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                    bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                    bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
        acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    }
    // 這個(gè)acc就是和資源、環(huán)境有關(guān)的aware,執(zhí)行需要doPrivileged
    if (acc != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareInterfaces(bean);
            return null;
        }, acc);
    }
    else {
        invokeAwareInterfaces(bean);
    }

    return bean;
}

private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
        }
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }
        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
        }
        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
        }
        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
        }
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }
}

環(huán)境相關(guān)的接口都invoke后,自定義的后置處理器開始執(zhí)行

@Component
public class CustomInstantiationAwareBPP implements InstantiationAwareBeanPostProcessor {
// 還是這個(gè)類,熟悉的味道,伴隨著bean的整個(gè)實(shí)例化生命周期
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (beanName.equals("A")) {
        System.out.println("在真正初始化之前,對(duì)bean A 修改一下");
    }
    return bean;
}

// 其他生命周期的調(diào)用方法
}

還記得我們前面說的CommonAnnotationBeanPostProcessor合并bean的時(shí)候,同樣是這個(gè)后置處理器,調(diào)用它的父類InitDestroyAnnotationBeanPostProcessor@PostConstruct@PreDestroy注解的方法存到當(dāng)前這個(gè)后置處理器了么,下面就是要invoke他們的時(shí)候了

image
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 找到之前 找出的 `@PostConstruct` 和 `@PreDestroy`
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        // 執(zhí)行他們
        metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    }
    return bean;
}

第八次、在完成bean的初始化后 - 完成代理

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

這里就不貼自定義的后置處理器了,和前面before大同小異

第一個(gè)后置處理器是PostProcessorRegistrationDelegate

他首先會(huì)check一下,在當(dāng)前正在創(chuàng)建的bean時(shí),不是BeanPostProcessor,不是spring的基礎(chǔ)類型bean,并且?。?! 重點(diǎn)來了:如果當(dāng)前工廠的所有bean 后置處理器的數(shù)量小于實(shí)際執(zhí)行后置處理器數(shù)量,就會(huì)打個(gè)info,這里有很多人踩坑。先看下代碼:

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
            this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
        if (logger.isInfoEnabled()) {
            logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
                    "] is not eligible for getting processed by all BeanPostProcessors " +
                    "(for example: not eligible for auto-proxying)");
        }
    }
    return bean;
}

踩什么坑?比如,看下面打的日志,Spring說 你當(dāng)前這個(gè)bean,還沒有準(zhǔn)備好被所有后置處理器調(diào)用,比如自動(dòng)代理(造成代理失?。?。

這就是很多人突然發(fā)現(xiàn)自己項(xiàng)目,事務(wù)、AOP或者異步失效了,就很懵逼。

要怎么解決呢?

比如你為了省麻煩,不想自己?jiǎn)为?dú)開個(gè)配置類,在以前項(xiàng)目代碼的一個(gè)使用比較低優(yōu)先級(jí)的BeanPostProcessor(比如order很低的)來完成這個(gè)業(yè)務(wù)bean的注入。當(dāng)注入這個(gè)bean的時(shí)候,因?yàn)樘幚硎聞?wù)、AOP的后置處理器還沒加載,自然也沒發(fā)代理這個(gè)bean,從而顯得他們都失效

說人話就是,自己把業(yè)務(wù)bean放到,Spring的后置處理器前面實(shí)例化了

解決方法就是,不偷懶,自己搞個(gè)配置類放進(jìn)去,保證在后面執(zhí)行就ok

第二個(gè)是AbstractAutoProxyCreator

就是看你需不需要代理,需要就給你整個(gè)代理
這個(gè)地方要結(jié)合著,前面,循環(huán)依賴來看,當(dāng) A->B->A 時(shí),A如果需要被代理,那么earlyProxyReferences就會(huì)有A的cache,從而在這里完成代理

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

最后一個(gè)起作用的是 ApplicationListenerDetector

這兒其實(shí)就看一行代碼 this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);

將監(jiān)聽器當(dāng)?shù)拉h(huán)境中

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean instanceof ApplicationListener) {
        // potentially not detected as a listener by getBeanNamesForType retrieval
        Boolean flag = this.singletonNames.get(beanName);
        if (Boolean.TRUE.equals(flag)) {
            // singleton bean (top-level or inner): register on the fly
            this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
        }
        else if (Boolean.FALSE.equals(flag)) {
            if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
                // inner bean with other scope - can't reliably process events
                logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                        "but is not reachable for event multicasting by its containing ApplicationContext " +
                        "because it does not have singleton scope. Only top-level listener beans are allowed " +
                        "to be of non-singleton scope.");
            }
            this.singletonNames.remove(beanName);
        }
    }
    return bean;
}

啪啪啪 終于tm的寫完了

之后就是一些getBean的收尾工作,清除緩存、添加bean到單例池等等

image

下一篇文章我們來填上面的坑 - 創(chuàng)建bean時(shí)如何推斷一個(gè)bean的構(gòu)造方法

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

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