Bean生命周期涉及到的所有后置处理器及其执行时机
看了本篇文章,你会有如下收获
- 了解
Bean
生命周期流程 - 清楚有哪些后置处理器,及其在
bean
生命周期他们的执行时机 -
"实诚"
的动态
的debug
gif
- 看到满满的干货,然后才能和面试官对线
要想看懂这篇文章,你应该大致了解Spring的大致执行流程,不过不了解的小伙伴别担心,看看下面这段话
对下面流程不太熟悉的小伙伴也不需要担心,大概了解就行
[图片上传失败...(image-485ddf-1598633659159)]](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f3f13ff5e57945059002d0762cab067b~tplv-k3u1fbpfcp-zoom-1.image)
执行流程里面的 postProcessor 主要是用来在某个 生命周期 执行的时机点 调用而已
我都说到这个份儿上了,童鞋们最好都跟着Debug一下噢
言归正传 有个大前提:这里讨论的是,在容器refresh末尾的时候,需要完成Bean工厂初始化回调(finishBeanFactoryInitialization
, 在回调的最后会预先加载Bean(preInstantiateSingletons
),从而调用 getBean
的逻辑来完成初始化
重要的话说n次 最好跟着Debug噢
,就拿你自己的web项目
debug也行
想下载源码写 test 的童靴,如果不会请在下面评论区告诉我,我会补上Spring源码搭建的教材噢!
如果还嫌麻烦,我可以把我搭建好的项目传到gitee或者github,大家拉下来就能用了。
好,铺垫到这儿,我们开始吧
一、接管bean创建逻辑,返回自定义bean
从getBean流程开始,当bean
创建的时候需要提前解析这个bean
的class
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 如果这个bean没有被解析过,这里第一次进来肯定没解析过
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
// 重要!!!合成类知识,不想看这一大段文字,可以直接跳过,到下面if语句中
// 这里的Synthetic指的是这个类是不是合成类,比如当这个类有个内部类的时候,这个类不能访问到内部类的私有变量
// 但是这里jvm想要支持,怎么办呢?
// 所以它采取了一种策略,创建一个新的类出来,合成这个类和内部类,使程序员在使用的时候看起来,可以直接访问内部类,这里不展开了
// 感兴趣的兄dei可以自己写个类,看看class文件,会多出来一个 xxx1.class
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 看到这儿,从方法名就可以初步猜测这里是推断出class对象的
// 但是他是怎么推断出来的呢,emmmmm,嘿嘿,这里挖个坑,后面讲
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 这里开始正式调用后置处理器,系统内置的后置处理器啥都没干
// 除非你自己写了个后置处理器,看下个代码框
// 而且你这个后置处理器提前给别人返回了一个bean,那么就会直接进入下面的判断完成初始化,直接结束
// 如果你的公司想要自己去实现bean的初始化流程,那么就应该在这里实现
// 之后Spring就会直接返回你给的这个对象,如下所示
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 执行后置处理,不同时机
// 下面有自定义的例子,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返回,如果我们开启了自动代理,Spring也会把我们自定义的bean进行代理,感兴趣的童鞋可以 在配置类上加个
@EnableAspectJAutoProxy
,写个Aspect
切面指定到我们的A
类试试
二、自行推断构造方法
我们继续去看第二个bean生命周期的执行时机,接下来,Spring就会去创建bean
,那么问题来了,要创建一个bean,首先创建它的对象,如何创建对象?通过构造方法 反射创建?没错,但如果你提供了多个构造方法,我怎么知道要用哪个构造方法创建呢(下节详解,这里大概知道就行)Spring自己对构造方法做了推断,而推断逻辑则是放在了 AutowiredAnnotationBeanPostProcessor
中去推断
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 可以自己去实现SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors
// 从而实现覆盖 AutowiredAnnotationBeanPostProcessor 完成自定义
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
Spring 通过 AutowiredAnnotationBeanPostProcessor
实现的 推断构造方法,我们挖个坑,放到下篇专门讲解推断构造方法讲。
来来来,干了这一杯,还有··
对不起串台了
来来来,我们自己写个超简单的自定义后置处理器实现推断构造方法,去覆盖Spring自己的推断方法
@Component
public class CustomSmartInstantiationawareBPP implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("自己来推断构造方法");
return beanClass.getDeclaredConstructors();
}
}
结果:
可以看到创建所有bean
的时候都被我们自定义的替换了
三、合并bean
首先我们来搞清楚一件事,什么是合并bean
,在Spring中存在 三个BeanDefinition
-
RootBeanDefinition
父BD -
ChildBeanDefinition
子BD -
GenericBeanDefinition
既可作用于父BD,又可是于子BD
现在有这么个情况,和java继承思想类似,当某个子BD继承了父BD,在使用时可以通过子BD操作父类属性(子类继承父类)。
所以必须要合并一下BD,让子类也有父类的属性
父子BD解释通了。那为什么不直接用GenericBD
,或许是历史遗留原因,现在的版本必须向前兼容,故而必须保留。
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.
// 这里已经写得很清楚了,允许后置处理器去修改合并bean,我们来看看到底是哪个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切入点和资源切入@Resource xml的WebServiceRef 和 EJB
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 遍历所有方法,找到所有 @PostConstruct 和 @PreDestroy 注解的方法 并把他们放到 bd 中 把他们放入 bd 的 checkedInitMethods 和 checkedDestroyMethods属性中
// 这里是调用了父类 “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);
}
接下来,我们自己实现一个后置处理器,来找一个我们自己定义的注解,并把它也存到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);
// 搞个和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? "必输":"非必输";
// 用来保存 注解信息,这样下次需要去注入时,再通过该element注入就好
System.out.println("找到一个ZWL注解,在" + clazz.getSimpleName() + "类中,是" + requiredStr + "的");
currElements.add(new ZWLFieldElement(field, required));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
// 返回封装后解析到的信息,用InjectionMetadata统一处理
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
四、提前使用工厂暴露代理对象
就如我们在上一篇文章,循环依赖提到的,传送门 ,在过程 A->B->A 给B注入A对象时,如果A已经被代理,那么必须给他注入一个代理对象才行,所以这个地方就是要通过工厂来生产了,而这个工厂的运作方式,就是通过后置处理器返回的代理对象
上代码,一清二楚
@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) {
// 调用工厂方法生产
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方法 创建了一个代理对象
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
正经的分割线,预警!接下来的两个后置处理器执行时机,是在注入属性时执行的
五、在bean注入属性前,可以对bean做一些判断修改,也可以直接中断bean属性注入(判断是否需要继续注入属性)
// 在这里 Spring内置的beanPostProcessor 什么事也没干
// 所以只能我们自定义一个
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;
}
}
}
}
// 来看看我们的自定义的例子,这里复用了之前的 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("在初始化之前来整一个A");
result = new ObjectA();
}
// 避免返回自定义对象,结束创建bean
// return result;
return null;
}
// 新的在这里!!!
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("在属性真正注入之前对" + beanName + "bean做些小动作");
// 是否继续注入属性,true则继续
return true;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("A")) {
System.out.println("A已经整完了,好了,拿走吧");
}
return bean;
}
}
执行的结果当然就是打印出来了这句话
六、属性注入
后置处理器的执行点
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);
}
// 改方法已经遗弃不建议使用
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
这里 CommonAnnotationBeanPostProcessor
会去注入之前提到过的 @Resource
、WebServiceRef
、EJB
的属性或者调用方法 设置值
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 还是和前面合并bean的功能一样,查找@Resource等信息,如果之前有解析过,那么这里就不会解析了,直接拿出缓存中的值
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
的属性或方法 然后查找它合适的值然后注入,至于如何查找值,这个知识点下篇文章详解
@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("在初始化之前来整一个A");
result = new ObjectA();
}
// 避免返回自定义对象,结束创建bean
// return result;
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("在属性真正注入之前对" + beanName + "bean做些小动作");
// 是否继续注入属性,true则继续
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("对bean的PropertyValues 做修改,然后注入对应属性");
return pvs;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("A")) {
System.out.println("A已经整完了,好了,拿走吧");
}
return bean;
}
}
又到了画分割线的季节,下面才是猛男该看的东西
多图预警!!!
也就一般这么猛,言归正传,我们继续
接下来就是在bean完成属性注入后,对bean进行初始化的执行时机
七、在初始化前,调用各种aware
首先来看下初始化整体的调用逻辑
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 调用 bean 的aware类型的方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 在初始化之前调用
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用实现的初始化的方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 在初始化之后调用
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
初始化之前的切入点
@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
主要是去触发一些实现了环境事件监听
、资源load``信息发布
等等事件接口
@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();
}
// 这个acc就是和资源、环境有关的aware,执行需要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);
}
}
}
环境相关的接口都invoke后,自定义的后置处理器开始执行
@Component
public class CustomInstantiationAwareBPP implements InstantiationAwareBeanPostProcessor {
// 还是这个类,熟悉的味道,伴随着bean的整个实例化生命周期
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("A")) {
System.out.println("在真正初始化之前,对bean A 修改一下");
}
return bean;
}
// 其他生命周期的调用方法
}
还记得我们前面说的CommonAnnotationBeanPostProcessor
在合并bean
的时候,同样是这个后置处理器
,调用它的父类InitDestroyAnnotationBeanPostProcessor
将@PostConstruct
和 @PreDestroy
注解的方法存到当前这个后置处理器
了么,下面就是要invoke他们的时候了
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 找到之前 找出的 `@PostConstruct` 和 `@PreDestroy`
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 执行他们
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大同小异
第一个后置处理器是PostProcessorRegistrationDelegate
他首先会check一下,在当前正在创建的bean时,不是BeanPostProcessor,不是spring的基础类型bean,并且!!! 重点来了:如果当前工厂的所有bean 后置处理器的数量小于实际执行后置处理器数量,就会打个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说 你当前这个bean,还没有准备好被所有后置处理器调用,比如自动代理(造成代理失败)。
这就是很多人突然发现自己项目,事务、AOP或者异步失效了,就很懵逼。
要怎么解决呢?
比如你为了省麻烦,不想自己单独开个配置类,在以前项目代码的一个使用比较低优先级的BeanPostProcessor
(比如order很低的)来完成这个业务bean
的注入。当注入这个bean
的时候,因为处理事务、AOP的后置处理器还没加载,自然也没发代理这个bean
,从而显得他们都失效
说人话就是,自己把业务bean放到,Spring的后置处理器前面实例化了
解决方法就是,不偷懒,自己搞个配置类放进去,保证在后面执行就ok
第二个是AbstractAutoProxyCreator
就是看你需不需要代理,需要就给你整个代理
这个地方要结合着,前面,循环依赖来看,当 A->B->A 时,A如果需要被代理,那么earlyProxyReferences就会有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;
}
最后一个起作用的是 ApplicationListenerDetector
这儿其实就看一行代码 this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
将监听器当道环境中
@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到单例池等等
下一篇文章我们来填上面的坑 - 创建bean时如何推断一个bean的构造方法