0
点赞
收藏
分享

微信扫一扫

Spring 注解驱动开发_生命周期-BeanPostProcessor 原理

慕容冲_a4b8 2022-03-30 阅读 79
spring

本节主要来探讨一下 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 属性赋值

举报

相关推荐

0 条评论