本节主要来探讨一下 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();
}
}
原理
首先在 MyBeanPostProcessor 的两个方法上打上断点
以 DEBUG 形式运行测试方法,先来看一下方法调用栈:
先根据方法调用栈梳理一下大致的流程:
重点看一下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;
}
断点执行情况如下:
继续执行到 populateBean 方法,该方法主要用于为 bean 属性赋值