Bean生命周期涉及到的所有后置處理器及其執(zhí)行時(shí)機(jī)
看了本篇文章,你會(huì)有如下收獲
- 了解
Bean生命周期流程 - 清楚有哪些后置處理器,及其在
bean生命周期他們的執(zhí)行時(shí)機(jī) -
"實(shí)誠(chéng)"的動(dòng)態(tài)的debuggif

- 看到滿滿的干貨,然后才能和面試官對(duì)線
要想看懂這篇文章,你應(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è)bean的class
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;
}
[圖片上傳失敗...(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自己的推斷方法
@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é)果:
可以看到創(chuàng)建所有bean的時(shí)候都被我們自定義的替換了
三、合并bean
首先我們來搞清楚一件事,什么是合并bean,在Spring中存在 三個(gè)BeanDefinition
-
RootBeanDefinition父BD -
ChildBeanDefinition子BD -
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
四、提前使用工廠暴露代理對(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)然就是打印出來了這句話
六、屬性注入
后置處理器的執(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ù)警?。?!
也就一般這么猛,言歸正傳,我們繼續(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í)候了
@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到單例池等等
下一篇文章我們來填上面的坑 - 創(chuàng)建bean時(shí)如何推斷一個(gè)bean的構(gòu)造方法