Spring bean的生命周期

Bean 定义注册阶段

程序启动阶段,应用从XML文件或者注解中找到bean definition并注册到Spring IoC容器,代码入口参考 :

	// 参考代码 : 
	// package : org.springframework.beans.factory.support
	// class : DefaultListableBeanFactory
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
			// ... 省略实现
	}			

Bean定义注册到Spring IoC容器并不表示已经有了Bean实例,只是表明如果要获取相应的Bean实例,Spring IoC容器已经拥有了相应的Bean实例创建的完整信息。

Bean 实例获取阶段

当获取一个Bean实例时,可能是因为以下操作之一 :

  1. 某个bean需要被注入到其他bean;
  2. 某个bean被用户直接调用Spring IoC容器上的getBean()方法获取其实例;

最终上面的这些操作都会导致一个bean实例被准备(新建或者使用一个已经缓存的bean),代码参考入口:

	// package : org.springframework.beans.factory.support
	// class : AbstractBeanFactory (DefaultListableBeanFactory的父类)
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
			// 省略实现
	}

下面主要看一个bean被新建的过程,代码参考入口:

	// package : org.springframework.beans.factory.support
	// class : AbstractAutowireCapableBeanFactory (DefaultListableBeanFactory的父类)
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, 
		final @Nullable Object[] args) throws BeanCreationException
			// 省略实现
	}
  1. 实例化bean对象(可以理解成new一个对象);
  2. Spring依赖注入填充所有bean definition中涉及到的属性;

    1.@Autowired依赖注入在此阶段完成,此过程可能会触发其他bean实例的准备;
    2.@Value注解注入来自配置文件的属性的设置也发生在此阶段;

  3. 初始化bean;
    1. Aware 接口方法调用;

      1. 如果bean实现了接口 BeanNameAware, 调用方法setBeanName(该bean的ID)
      2. 如果bean实现了接口 BeanClassLoaderAware,调用方法setBeanClassLoader(容器记录的bean的classLoader);
      3. 如果bean实现了接口 BeanFactoryAware, 调用方法setBeanName(该bean的ID)
    2. BeanPostProcessor#postProcessBeforeInitialization()应用到该bean;

      Spring 容器标准情况下会关联两个BeanPostProcessor :
      1. ApplicationContextAwareProcessor
      2. ApplicationListenerDetector

      在应用 ApplicationContextAwareProcessor#postProcessBeforeInitialization() 时 :
      1. 如果bean实现了接口 EnvironmentAware, 调用方法setEnvironment()
      2. 如果bean实现了接口 EmbeddedValueResolverAware,调用方法setEmbeddedValueResolver();
      3. 如果bean实现了接口 ResourceLoaderAware, 调用方法setResourceLoader()
      4. 如果bean实现了接口 ApplicationEventPublisherAware, 调用方法setApplicationEventPublisher()
      5. 如果bean实现了接口 ResourceLoaderAware, 调用方法setResourceLoader()
      6. 如果bean实现了接口 MessageSourceAware, 调用方法setMessageSource()
      7. 如果bean实现了接口 ApplicationContextAware, 调用方法setApplicationContext()

    3. 如果该bean上有JSR-250注解@PostConstruct注解的方法,调用该方法;

    4. 如果该bean实现了接口InitializingBean,容器调用该bean的方法afterPropertiesSet();

    5. 如果该bean上定义了设置了 init 属性,容器调用该属性对应的bean方法;

      如果想对一个bean定制初始化逻辑,要么实现接口InitializingBean,要么在定义时设置init属性。
      如果两种方法同时使用,仅仅使用接口InitializingBean定义的初始化方法afterPropertiesSet()

      代码参考 :

      protected void invokeInitMethods(String beanName, final Object bean, 
      @Nullable RootBeanDefinition mbd) throws Throwable() {
      	// 省略实现
      }
      
    6. BeanPostProcessor#postProcessAfterInitialization()应用到在该bean

Bean 实例销毁阶段

bean不再需要时,会被销毁 :

  1. 如果该bean上有JSR-250注解@PreDestroy注解的方法,调用该方法;
  2. 如果该bean实现了DisposableBean接口,会调用该bean实现的该接口的destroy()方法;
  3. 如果这个bean定义中设置了 destroy 属性,容器调用该属性对应的bean方法。

相关文章

例子演示Spring bean生命周期方法的调用顺序

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值