Spring Bean生命周期执行流程详解


一、什么是Spring Bean生命周期?

Spring Bean生命周期是指从Bean的创建到销毁的整个过程,其中涉及到Spring容器对Bean的一系列处理操作,包对Bean的实例化、依赖注入、初始化和销毁。Spring框架中Bean的生命周期主要包括以下关键步骤:

  1. 实例化BeanSpring容器根据Bean的定义从容器中取出Bean的类,通过反射机制进行实例化。
  2. 属性填充:Spring容器从Bean定义中获取属性值,将这些属性值注入到新创建的Bean实例中,这个过程也叫做依赖注入。
  3. Aware接口回调:如果Bean涉及到实现了BeanNameAwareBeanClassLoaderAwareBeanFactoryAware接口,则会触发BeanNameAware.setBeanNameBeanClassLoaderAware.setBeanClassLoaderBeanFactory.setBeanFactory方法的调用。
  4. BeanPostProcessor接口回调:触发前置方法BeanPostProcessor.postProcessBeforeInitialization。注意的是ApplicationContextAwareProcessorInitDestroyAnnotationBeanPostProcessor都是BeanPostProcessor的实现类,因此可能触发ApplicationContextAwaresetApplicationContext方法回调和init-Method回调。
  5. InitializingBean接口回调:触发InitializingBean.afterPropertiesSet方法。
  6. BeanPostPorcessor接口回调:触发后置方法BeanPostProcessor.postProcessAfterInitialization方法。
  7. Bean初始化完成,可以投入使用
  8. Bean实现了DisposableBean接口时,Spring容器关闭时,会回调DisposableBean.destory方法。
  9. Bean被销毁,生命周期结束。

工作流程图:

在这里插入图片描述


二、Bean生命周期执行流程验证

1.编写测试代码验证结果

定义一个LifeCycleBean类,将其作为SpringBean进行管理,让其实现BeanNameAware, BeanFactoryAware, BeanPostProcessor, ApplicationContextAware, InitializingBean, DisposableBean接口,在实现方法中打印对应的信息,查看方法调用的顺序。


import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

@Component
public class LifeCycleBean implements BeanNameAware, BeanFactoryAware, BeanPostProcessor, ApplicationContextAware, InitializingBean, DisposableBean {

    //前置处理是否被调用标识
    private volatile boolean beforeInitializationInvoked = false;
    //后置处理是否被调用标识
    private volatile boolean afterInitializationInvoked = false;

    @Override
    public void setBeanName(String name) {
        System.out.println("BeanNameAware.name be invoked");
    }

    @PostConstruct
    public void init() {
        System.out.println("PostConstruct.init be invoked");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean.destroy be invoked");
    }

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

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware.setApplicationContext be invoked");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!beforeInitializationInvoked) {
            beforeInitializationInvoked = true;
            System.out.println("BeanPostProcessor.postProcessBeforeInitialization be invoked");
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (!afterInitializationInvoked) {
            afterInitializationInvoked = true;
            System.out.println("BeanPostProcessor.postProcessAfterInitialization be invoked");
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware.setBeanFactory be invoked");
    }
}

启动项目,查看控制台打印结果如下:
在这里插入图片描述
关闭容器后,控制台打印如下:
在这里插入图片描述
因此可以得出,Bean启动后,初始化的执行顺序是:BeanNameAware->BeanFactoryAware->ApplicationContextAware(由ApplicationContextAwareProcessor调用)->PostConstruct(由InitDestroyAnnotationBeanPostProcessor调用)->BeanPostProcessor.postProcessBeforeInitialization(自定义)->InitializingBean.afterPropertiesSet->BeanPostProcessor.postProcessAfterInitialization–>DisposableBean.destory


2.源码追溯Bean初始化回调过程

通过断点可以得出Bean初始化的入口在AbstractAutowireCapableBeanFactory.initializeBean方法。

protected Object initializeBean(String beanName, 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;
	}

其中的一个方法invokeAwareMethods的命名十分明显,用于调用一些Aware接口的实现类,进入invokeAwareMethods方法后,通过判断当前bean是否为Aware类型,如果是则进一步判断是Aware接口下的哪一种类型,然后进行类型转换调用对应的方法。

	private void invokeAwareMethods(String beanName, 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);
			}
		}
	}

执行完invokeAwareMethods后,则调用initializeBean方法中的applyBeanPostProcessorsBeforeInitialization方法,通过遍历现有的BeanPostProcessor类,依次调用其postProcessBeforeInitialization方法。

	@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;
	}

其中重点关注ApplicationContextAwareProcessorInitDestroyAnnotationBeanPostProcessor两个类,他们都属于BeanPostPorcessor的实现类,因此在循环时都会调用其postProcessBeforeInitialization方法。ApplicationContextAwareProcessor.postProcessBeforeInitialization方法中有一个比较重要的方法invokeAwareInterfaces,该方法也是用于回调一些实现了Aware接口的类。其中ApplicationContextAware.setApplicationContext就是在此处被调用,当然还涉及到EnvironmentAwareEmbeddedValueResolverAwareMessageSourceAware等的回调。

	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);
		}
	}

InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization方法重要是通过反射机制调用被注释PostConstruct修饰的init-Method.

在完成applyBeanPostProcessorsBeforeInitialization调用后,则会调用invokeInitMethods方法, 如果Bean实现了InitializingBean接口,Spring容器会调用其afterPropertiesSet()方法。

protected void invokeInitMethods(String beanName, 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);
			}
		}
	}

最调用applyBeanPostProcessorsAfterInitialization方法,通过遍历BeanPostProcessor的实现类,调用其postProcessAfterInitialization后置方法。

	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;
	}
Spring Bean生命周期可以分为以下过程:实例化、属性注入、BeanPostProcessor前置处理、初始化、BeanPostProcessor后置处理、销毁。 首先,在容器初始化时,Spring会读取配置文件或注解等方式,找到并实例化BeanBean的实例化可以通过构造器进行,也可以通过工厂方法进行。当容器调用构造器或者工厂方法时,Bean就会被实例化,但此时Bean还未被初始化。 其次,在实例化后,Spring会将Bean的属性注入。属性注入的方式有两种:setter注入和构造器注入。如果选择setter注入,则Spring会通过反射机制将属性值注入到Bean中。如果是构造器注入,则Spring容器会找到匹配的构造器,并将属性值注入到Bean中。 接下来,对Bean进行初始化。在初始化过程中,Spring框架会使用各种回调方法,以达到对Bean的加工和改造的目的。Bean的初始化可以通过实现接口来完成,也可以通过注解等方式完成。其中最常用的是InitializingBean接口和@PostConstruct注解。 初始化完成后,Spring会进行BeanPostProcessor前置处理。在该处理过程中,Spring会检查是否有实现BeanPostProcessor接口的类,如果有则会调用其中两个方法postProcessBeforeInitialization(…)和postProcessAfterInitialization(…),分别在Bean的初始化前和初始化后进行处理。 最后,当Bean不再被使用时,Spring会调用销毁方法进行销毁操作。Bean的销毁可以通过实现DisposableBean接口完成,也可以通过注解等方式完成。其中最常用的是DisposableBean接口和@PreDestroy注解。 综上所述,Spring Bean生命周期流程包括:实例化、属性注入、BeanPostProcessor前置处理、初始化、BeanPostProcessor后置处理、销毁。对于每个BeanSpring会按照以上流程进行处理,确保Bean能够达到预期的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值