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
实例时,可能是因为以下操作之一 :
- 某个
bean
需要被注入到其他bean
; - 某个
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
// 省略实现
}
- 实例化
bean
对象(可以理解成new
一个对象); Spring
依赖注入填充所有bean definition
中涉及到的属性;1.
@Autowired
依赖注入在此阶段完成,此过程可能会触发其他bean实例的准备;
2.@Value
注解注入来自配置文件的属性的设置也发生在此阶段;- 初始化
bean
;-
Aware
接口方法调用;- 如果
bean
实现了接口BeanNameAware
, 调用方法setBeanName(该bean的ID)
; - 如果
bean
实现了接口BeanClassLoaderAware
,调用方法setBeanClassLoader(容器记录的bean的classLoader)
; - 如果
bean
实现了接口BeanFactoryAware
, 调用方法setBeanName(该bean的ID)
;
- 如果
-
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()
; -
如果该
bean
上有JSR-250
注解@PostConstruct
注解的方法,调用该方法; -
如果该
bean
实现了接口InitializingBean
,容器调用该bean
的方法afterPropertiesSet()
; -
如果该
bean
上定义了设置了init
属性,容器调用该属性对应的bean
方法;如果想对一个
bean
定制初始化逻辑,要么实现接口InitializingBean
,要么在定义时设置init
属性。
如果两种方法同时使用,仅仅使用接口InitializingBean
定义的初始化方法afterPropertiesSet()
。代码参考 :
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable() { // 省略实现 }
-
BeanPostProcessor#postProcessAfterInitialization()
应用到在该bean
。
-
Bean 实例销毁阶段
当bean
不再需要时,会被销毁 :
- 如果该
bean
上有JSR-250
注解@PreDestroy
注解的方法,调用该方法; - 如果该
bean
实现了DisposableBean
接口,会调用该bean
实现的该接口的destroy()
方法; - 如果这个
bean
定义中设置了destroy
属性,容器调用该属性对应的bean
方法。