本节主要来探讨一下 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 的两个方法上打上断点

spring initializer 开始收费_sed


以 DEBUG 形式运行测试方法,先来看一下方法调用栈:

spring initializer 开始收费_sed_02


先根据方法调用栈梳理一下大致的流程:

spring initializer 开始收费_spring_03

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 有很多的实现类,以下截图也只展示了其中的一部分:

spring initializer 开始收费_System_04


其中,我们以 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,则可以获取到当前容器的信息。