Spring bean的生命周期和扩展

AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,以具体实例看bean生命周期的一些执行阶段

bean生命周期流程

|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 生命周期 | 扩展处理 | 说明 |
| 实例化:createBeanInstance | 构造方法, 如@Autowired的构造方法注入依赖bean | 如UserService构造方法注入AppDAO: > > @Autowired > public UserService(AppDAO appDAO) { > System.out.println("@Autowired appDAO:" + appDAO); > this.appDAO = appDAO; > } > |
| 属性设置:populateBean | 如setter方法注入的依赖 如@Autoware的filed注入 | 如UserService中注入UserDAO: > > @Resource(name = "u") > public void setUserDAO(UserDAO userDAO) { > System.out.println("setUserDAO:" + userDAO); > this.userDAO = userDAO; > } > |
| 初始化:initializeBean | 1. BeanPostProcessor#postProcessBeforeInitialization 2. @PostConstruct 3. InitializingBean#afterPropertiesSet initMethod 4. BeanPostProcessor#postProcessAfterInitialization | 上一步骤属性设置完后,初始化方法前后都可以扩展。 例如BeanPostProcessor#postProcessBeforeInitialization,直接改变了set注入的appDAO对象 > > @Component > public class ServiceBeanPostProcessor implements BeanPostProcessor { > @Override > public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { > // Bean 初始化前的逻辑 > if (beanName.equals("userService")) { > UserService userService = (UserService)bean; > AppDAO appDAO = new AppDAOImpl2(); > userService.setAppDAO(appDAO); > System.out.println("postProcessBeforeInitialization:" + ":" + bean); > } > return bean; > } > |
| 销毁 | 1. @PreDestroy 2. DisposableBean#destroy destroyMethod | |

附org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

java 复制代码
/**
	 * Actually create the specified bean. Pre-creation processing has already happened
	 * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
	 * <p>Differentiates between default bean instantiation, use of a
	 * factory method, and autowiring a constructor.
	 * @param beanName the name of the bean
	 * @param mbd the merged bean definition for the bean
	 * @param args explicit arguments to use for constructor or factory method invocation
	 * @return a new instance of the bean
	 * @throws BeanCreationException if the bean could not be created
	 * @see #instantiateBean
	 * @see #instantiateUsingFactoryMethod
	 * @see #autowireConstructor
	 */
	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.
		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(beanName, mbd, instanceWrapper);
			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 " +
								"'getBeanNamesOfType' 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;
	}

扩展执行

接上文:AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,来看这些BeanPostProcessor如何起作用

测试bean定义类如下

java 复制代码
@Service("userService")
public class UserService implements InitializingBean, DisposableBean {

    private String userServiceName;

    private UserDAO userDAO;
    private AppDAO appDAO;

    /**
     * field 注入
     */
    @Autowired
    private CommonService commonService;

    public UserService() {
        System.out.println("constructor");
    }

    /**
     * 类似于 InitializingBean 的 afterPropertiesSet() 方法
     */
    @PostConstruct
    public void init() {
        System.out.println("PostConstruct userService");
        System.out.println("userDAO is not null:" + (userDAO != null));
        System.out.println("appDAO is not null:" + (appDAO != null));
        userServiceName = "selfUserService";
    }

    /**
     * setter注入
     * @param userDAO
     */
    @Resource(name = "u")
    public void setUserDAO(UserDAO userDAO) {
        System.out.println("setUserDAO:" + userDAO);
        this.userDAO = userDAO;
    }

    /**
     * 构造器注入
     * @param appDAO
     */
    @Autowired
    public UserService(AppDAO appDAO) {
        System.out.println("@Autowired appDAO:" + appDAO);
        this.appDAO = appDAO;
    }

    public void add(User user) {
        userDAO.save(user);
    }

    public UserDAO getUserDAO() {
        return userDAO;
    }

    /**
     * 类似于 DisposableBean 的 destroy() 方法
     */
    @PreDestroy
    public void preDestroy() {
        System.out.println("preDestroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet userService");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("destroy userService");

    }

    public void setUserServiceName(String userServiceName) {
        this.userServiceName = userServiceName;
    }

    public void setAppDAO(AppDAO appDAO) {
        this.appDAO = appDAO;
    }

    @Override
    public String toString() {
        return "UserService{" +
                "userServiceName='" + userServiceName + '\'' +
                ", userDAO=" + userDAO +
                ", appDAO=" + appDAO +
                ", commonService=" + commonService +
                '}';
    }
}

InstantiationAwareBeanPostProcessors:SmartInstantiationAwareBeanPostProcessor

推断构造函数,最后是AutowiredAnnotationBeanPostProcessor完成构造函数的推断

最后判断有@Autowired的构造函数 完成实例化过程

InstantiationAwareBeanPostProcessor:CommonAnnotationBeanPostProcessor

populate阶段CommonAnnotationBeanPostProcessor完成setter注入

复制代码
/**
 * setter注入
 * @param userDAO
 */
@Resource(name = "u")
public void setUserDAO(UserDAO userDAO) {
    System.out.println("setUserDAO:" + userDAO);
    this.userDAO = userDAO;
}

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties

java 复制代码
@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
		try {
			metadata.inject(bean, beanName, pvs);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
		}
		return pvs;
	}

InstantiationAwareBeanPostProcessor:AutowiredAnnotationBeanPostProcessor

populate阶段AutowiredAnnotationBeanPostProcessor完成@Autorwired的filed的注入,具体可以再次阅读:Spring5.1.3 @Autorwired注解原理重新回顾-CSDN博客

BeanPostProcessor#postProcessBeforeInitialization

复制代码
initializeBean阶段会执行BeanPostProcessor的postProcessBeforeInitialization方法
执行自定义的BeanPostProcessor
执行CommonAnnotationBeanPostProcessor解析@PostConstruct注解
复制代码
@PostConstruct
public void init() {
    System.out.println("PostConstruct userService");
    System.out.println("userDAO is not null:" + (userDAO != null));
    System.out.println("appDAO is not null:" + (appDAO != null));
    userServiceName = "selfUserService";
}

执行InitializingBean的afterPropertiesSet方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

java 复制代码
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);
			}
		}
	}
BeanPostProcessor#postProcessAfterInitialization

InitializingBean最后阶段会执行BeanPostProcessor的postProcessAfterInitialization方法

本例

复制代码
@Component
public class ServiceBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // Bean 初始化前的逻辑
        if (beanName.equals("userService")) {
            UserService userService = (UserService)bean;
            AppDAO appDAO = new AppDAOImpl2();
            userService.setAppDAO(appDAO);
            System.out.println("postProcessBeforeInitialization:" + ":" + bean);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // Bean 初始化后的逻辑
        if (beanName.equals("userService")) {
            System.out.println("postProcessAfterInitialization:" + ":" + bean);
        }
        return bean;
    }
}
相关推荐
坐吃山猪20 小时前
SpringBoot01-配置文件
java·开发语言
我叫汪枫20 小时前
《Java餐厅的待客之道:BIO, NIO, AIO三种服务模式的进化》
java·开发语言·nio
yaoxtao21 小时前
java.nio.file.InvalidPathException异常
java·linux·ubuntu
Swift社区1 天前
从 JDK 1.8 切换到 JDK 21 时遇到 NoProviderFoundException 该如何解决?
java·开发语言
DKPT1 天前
JVM中如何调优新生代和老生代?
java·jvm·笔记·学习·spring
phltxy1 天前
JVM——Java虚拟机学习
java·jvm·学习
seabirdssss1 天前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续1 天前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben0441 天前
ReAct模式解读
java·ai