本节主要来探讨一下 BeanPostProcessor 的执行流程。
一、基础环境
实体类 Car
package org.example.pojo;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Car implements InitializingBean, DisposableBean {
private String brand;
private String price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getPrice() {
return price;
}
public Car(){
System.out.println("car constructor...");
}
public void initCar(){
System.out.println("car ... initCar...");
}
public void destoryCar(){
System.out.println("car ... destoryCar");
}
@Override
public void destroy() throws Exception {
System.out.println("car......DisposableBean......destory");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("car......InitializingBean......afterPropertiesSet");
}
@PostConstruct
public void initPostConstruct(){
System.out.println("car......initPostConstruct......");
}
@PreDestroy
public void initPreDestroy(){
System.out.println("car......initPreDestroy......");
}
}
创建 MyBeanPostProcessor 类,用于实现 BeanPostProcessor 接口
package org.example.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization..." + beanName + "--->" + bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization..." + beanName + "--->" + bean);
return bean;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price='" + price + '\'' +
'}';
}
}
配置类:
package org.example.config;
import org.example.pojo.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
@ComponentScan("org.example.processor")
public class InitAndDestoryTestConfig {
@Bean(initMethod = "initCar", destroyMethod = "destoryCar")
public Car car(){
Car car = new Car();
car.setBrand("奥迪");
car.setPrice("70万");
return car;
}
}
测试方法:
package org.example.test;
import org.example.config.*;
import org.example.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.Environment;
import java.sql.SQLOutput;
import java.util.Map;
public class AnnotationMainTest {
@Test
public void testInitAndDestory(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(InitAndDestoryTestConfig.class);
System.out.println("容器创建完成......");
Object car = ac.getBean("car");
Object car1 = ac.getBean("car");
System.out.println(car);
System.out.println(car1);
System.out.println(car == car1);
ac.close();
}
}
二、原理
2.1 执行流程
首先在 MyBeanPostProcessor 的两个方法上打上断点
以 DEBUG 形式运行测试方法,先来看一下方法调用栈:
先根据方法调用栈梳理一下大致的流程:
2.2 doCreateBean 方法
重点看一下AbstractAutowireCapableBeanFactory 类中 doCreateBean 方法
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) {
// 该方法用于创建 bean 实例
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.
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.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// populateBean 方法完成了 bean 的属性注入
populateBean(beanName, mbd, instanceWrapper);
// 初始化 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) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> 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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
该方法主要做了以下几件事:
- 通过 createBeanInstance 方法完成 bean 实例的创建
- 调用 populateBean 方法完成 bean 的属性注入
- 调用 initializeBean 方法完成 bean 的初始化
- 调用 registerDisposableBeanIfNecessary 方法,将一些需要在容器关闭时执行销毁方法的 bean 的添加到 bean 列表中
2.3 initializeBean 方法
重点看下 initializeBean 方法
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
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;
}
initializeBean 方法主要做了以下几件事:
- 调用 invokeAwareMethods,根据传入的参数 bean 实例,判断该 bean 实例实现了哪种 Aware 接口,并执行对应的方法。
- 调用 applyBeanPostProcessorsBeforeInitialization,执行后置处理器的初始化前方法。
- 调用 invokeInitMethods,执行初始化方法。
- 调用 applyBeanPostProcessorsAfterInitialization,执行后置处理器的初始化后方法。
2.4.1 invokeAwareMethods 方法
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
2.4.2 applyBeanPostProcessorsBeforeInitialization 方法
@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;
}
applyBeanPostProcessorsBeforeInitialization 方法获取到当前 bean 的所有的后置处理器,并循环遍历执行后置处理器的 postProcessBeforeInitialization 方法,并将执行结果返回。
2.4.3 invokeInitMethods 方法:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
invokeInitMethods 方法主要做了以下两件事:
- 如果当前 bean 实现了 InitializingBean 接口中的 afterPropertiesSet 方法,执行 afterPropertiesSet 方法
- 如果当前 bean 中指定了 initMethod(通过 @Bean 注解中 initMethod 属性或者Spring的 XML 配置文件中 bean 标签中的 init-method 属性),通过反射执行 initMethod 方法
2.4.4 applyBeanPostProcessorsAfterInitialization 方法
@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;
}
取出当前 bean 的所有后置处理器,循环遍历执行后置处理器的 postProcessAfterInitialization 方法
三、BeanPostProcessor 在 Spring 底层中的使用
接口 BeanPostProcessor 有很多的实现类,以下截图也只展示了其中的一部分:
其中,我们以 ApplicationContextAwareProcessor 为例,具体介绍下 BeanPostProcessor 接口在 Spring 中的应用。
先来看一下源码:
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
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 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);
}
}
}
ApplicationContextAwareProcessor 是 BeanPostProcessor 接口的实现类,所以也就实现了 postProcessBeforeInitialization 方法。在 postProcessBeforeInitialization 方法中,ApplicationContextAwareProcessor 主要做了两件事:
- 根据传入 bean 实例,判断当前 bean 实例是否实现了以下几个接口:
EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware,如果没有实现,则直接返回当前 bean 实例 - 如果实现了上述接口中的某一个,则调用 invokeAwareInterfaces 方法
这里说一下 Aware 接口:
public interface Aware {
}
Aware 接口实际上是一个标记接口(又称标签接口,指不包含任何方法的接口),具体的方法需要由各个子接口去确定,但通常该方法是一个仅接收单个参数的无返回值(void)的方法。实现 Aware 接口的 bean 在被初始化之后,可以通过这个无返回值的方法取得一些对应的资源。这也就表明不同的 Aware 子接口获取到的资源其实是不一样的。通过 ApplicationContextAwareProcessor 中的 invokeAwareInterfaces 方法便可以看出,如果当前 bean 实现了 EnvironmentAware 接口,则可以获取到当前容器运行的环境信息,如果当前 bean 实现了 ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware 或者 ApplicationContextAware,则可以获取到当前容器的信息。