Spring bean生命周期
前言
在Spring 框架中,代码定义的对象统一由Spring 容器管理,由Spring容器来创建,初始化。
那么一个bean的简版生命周期如下图:
图一
实例化一个bean对象,完成属性注入,执行初始化方法,此时bean可以被我们所使用,最后销毁。
Spring也赋予了一个bean在上述4个阶段中做一些增强的 *** 作,下文详细分析。
Spring bean生命周期Spring bean详细生命周期流程图:
图二
从doCreateBean() 方法开始
AbstractAutowireCapableBeanFactory抽象类:
省略部分代码
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @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);
}
Object bean = instanceWrapper.getWrappedInstance();
// Initialize the bean instance.
Object exposedObject = bean;
//属性填充
populateBean(beanName, mbd, instanceWrapper);
//初始化bean实例
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
在doCreateBean()方法中:
-
调用createBeanInstance() 方法完成对象实例化。
-
调用populateBean() 方法填充属性。
-
调用initializeBean() 方法完成bean实例的初始化方法回调。
initializeBean()方法
AbstractAutowireCapableBeanFactory抽象类:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
在initializeBean()方法中:
-
调用
invokeAwareMethods()
方法完成相关属性的注入。 -
初始化前调用bean后置处理器。
-
调用invokeInitMethods() 方法完成InitializingBean接口的回调。
-
初始化后调用bean后置处理器。
invokeAwareMethods() 方法注入相关属性
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);
}
}
}
applyBeanPostProcessorsBeforeInitialization()
和applyBeanPostProcessorsAfterInitialization()
方法中会获取bean后置处理器集合,依次执行:
-
ApplicationContextAwareProcessor 后置处理器:用于注入应用上下文属性。
-
InitDestroyAnnotationBeanPostProcessor 后置处理器:会找出@PostConstruct、@PreDestroy修饰的方法并执行。
自定义init方法
图二中调用自定义init方法invokeCustomInitMethod() 是指:
-
在xml配置bean时通过init-method标签指定。
-
或者通过注解@Bean(initMethod = "xxx")指定,默认为空。
@Component
@Slf4j
@Scope(value = "prototype")
@PropertySource({"classpath:bootstrap.yml"})
public class FullBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean,
InstantiationAwareBeanPostProcessor,
BeanPostProcessor,
DisposableBean {
private String name;
public FullBean() {
log.info("无参构造方法: {}", this);
}
@Value("${name}")
public void setName(String name) {
log.info("setName: {}", name);
this.name = name;
}
@Override
public void setBeanName(String name) {
log.info("beanName: {}", name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
log.info("beanFactory: {}", beanFactory.getClass());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("applicationContext: {}", applicationContext.getId());
}
@PostConstruct
public void postConstruct() {
log.info("postConstruct执行");
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("afterPropertiesSet执行");
}
@Override
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {
log.info("实例化前: {}", beanName);
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
log.info("实例化后: {}", beanName);
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
log.info("后处理属性注入: {}", beanName);
return null;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
log.info("属性注入: {}", beanName);
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
log.info("初始化前: {}", beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
log.info("初始化后: {}", beanName);
return bean;
}
@Override
public void destroy() throws Exception {
log.info("bean销毁");
}
}
执行结果:
实现BeanPostProcessor接口不生效原因单例模式下:
bean作用域默认为单例,也可以在bean上加 @Scope(value = "singleton")。 此时FullBean类中不会执行BeanPostProcessor接口覆盖的方法。
原因:
在AbstractApplicationContext#refresh() -> registerBeanPostProcessors()
方法中,FullBean由于实现了BeanPostProcessor接口,会被提前初始化,此时FullBean还未注册到BeanPostProcessor集合中。
refresh()方法分析见:Spring boot启动流程分析精简版
registerBeanPostProcessors()
方法会调用 PostProcessorRegistrationDelegate#registerBeanPostProcessors()
由于fullBean 是一个后置处理器类,那么此时fullBean 会先被创建,并放入单例缓存池中(缓存在DefaultSingletonBeanRegistry 类的singletonObjects 属性 map集合中),接着会将此bean注册到BeanPostProcessor 集合中。所以在单例情况下,实现了BeanPostProcessor 接口后,不会执行其实现的方法。
后面 getBean("fullBean")
直接从缓存中获取bean 实例。
原型模式下:
在类上注解@Scope(value = "prototype") 设置此bean作用域为原型模式。容器启动时由于fullBean 是后置处理器类,也不会执行。
Spring 应用容器启动完毕后,下一次getBean("fullBean")
时,会再次创建bean对象,此时会执行其后置处理器覆盖的方法。
本文分析了核心的关键流程,旨在了解bean 的生命周期。建议对照图二的流程图,去debug 源码会更加清晰。
注:类初始化和bean生命周期中的初始化不是一个概念
-
类初始化:Class.forName() 过程叫类初始化,会执行static block。返回一个class对象的引用。
-
文中bean初始化:执行对应的初始化方法。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)