本文主要介绍Spring
中所支持的常用的扩展接口,Spring
非常庞大且已成体系,众多的开发者包括Spring
框架的开发者不可能随意改动框架原来来实现个性化的需求,所以提供了许多扩展接口,遵循开闭原则
开闭原则定义:一个软件实体。如类/模块/函都应该对扩展开放,对修改关闭。
BeanPostProcessor 族
BeanPostProcessor是Spring实现『开闭原则』的一大体现,Spring 会在启动的不同阶段调用不同的BeanPostProcessor实现类,而这些BeanPostProcessor实现类由开发者自行实现(也有许多Spring内置的BeanPostProcessor)来实现启动中的各类需求。
实现了BeanPostProcessor
及其子类接口的Bean
将会被BeanFactory
在执行refresh
中某些特殊阶段进行回调,可以在这些方法内部修改或添加类似BeanDefinition
、创建Bean
代理等操作。
很多Spring
框架内部使用了BeanPostProcessor
来实现一些功能,例如@Autowired
功能是通过AutowiredAnnotationBeanPostProcessor
来实现。
BeanPostProcessor
1 | public interface BeanPostProcessor { |
postProcessBeforeInitialization
该方法将在Bean
实例化完成,并注入完属性后被调用,但优先于init-method
、InitializingBean#afterPropertiesSet
和InitializingBean#afterPropertiesSet
。
可以在该方法中返回包装对象或代理对象。
如果此方法返回null
,那么后续的BeanPostProcessor
将不会被调用。
postProcessAfterInitialization
该方法在postProcessBeforeInitialization
、InitializingBean#afterPropertiesSet
、init-method
调用完成之后被调用。
可以在该方法中返回包装对象或代理对象。
如果此方法返回null
,那么后续的BeanPostProcessor
将不会被调用。
InstantiationAwareBeanPostProcessor
1 | public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { |
postProcessBeforeInstantiation
该方法在实例化Bean
之前调用,可以在此处返回代理对象。
如果该方法返回值不为null
,那么其余的实例化操作将会被短路short-circuited
,包括其余的InstantiationAwareBeanPostProcessor
和实例属性的注入(populate
),但是会执行所有的BeanPostProcessor#postProcessAfterInitialization
。
postProcessAfterInstantiation
该方法在实例化Bean
之后,注入属性之前被调用。
如果该方法返回true
,那么后续的属性注入将被执行;如果返回false
,那么将不执行属性的注入,也不会执行其他InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
方法。
该方法适合在自动注入属性前进行自定义字段的注入。
postProcessPropertyValues
该方法在postProcessAfterInstantiation
方法调用之后,注入参数之前被调用,可以在此方法中添加或修改需要注入到Bean
中的参数。
@Resource
、@Autowire
等注解就是在此处实现自动注入的,扫描对应字段的注解,并将获取到的参数值传入该方法返回值PropertyValues
中,后续Spring 将自动把参数注入到对应的字段中。
如果该方法返回null,将不会执行属性的注入,也不会执行其他InstantiationAwareBeanPostProcessor#postProcessPropertyValues
方法。
SmartInstantiationAwareBeanPostProcessor
1 | public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { |
predictBeanType
预测并返回Bean
的实际类型,如果无法预测可以返回null
,一般在BeanDefinition
无法确定Bean
类型时调用。
determineCandidateConstructors
在Bean
实例化前被调用,用来确认实例化需要调用的构造方法
候选列表。
如果返回不为null
,那么不会执行其他的SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
,Spring将会在该返回列表中选择一个方法进行调用。如果所有的SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
均返回null
,那么将使用默认的无参构造方法
进行调用.
getEarlyBeanReference
出现循环依赖时将会被调用,通过此方法返回一个Bean
的引用。
MergedBeanDefinitionPostProcessor
1 | public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor { |
postProcessMergedBeanDefinition
该方法在合并完Bean
定义后被调用。
例如AutowiredAnnotationBeanPostProcessor
将在此处解析所有带@Autowire
注解的参数。
BeanFactoryPostProcessor 族
BeanFactoryPostProcessor
1 | public interface BeanFactoryPostProcessor { |
postProcessBeanFactory
该方法在所有BeanDefinition
被加载完成后,Bean
初始化之前被调用。
可以在此处修改已加载的BeanDefinition
,或添加自定义的BeanDefinition
,来实现动态注册Bean
。
BeanDefinitionRegistryPostProcessor
1 | public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { |
postProcessBeanDefinitionRegistry
该方法在所有BeanDefinition
被加载完成后,BeanFactoryPostProcessor#postProcessBeanFactory
之前被调用。
可以在此处修改已加载的BeanDefinition
,或添加自定义的BeanDefinition
,来实现动态注册Bean
;也可以在此方法中注册其他BeanDefinitionRegistryPostProcessor
,但如果当前Bean也是被其他BeanDefinitionRegistryPostProcessor#postProcessBeanFactory
加载的,那么当前Bean
加载的BeanDefinitionRegistryPostProcessor
将没有机会被执行。
Aware 族
实现了Aware
接口的Bean
将会在特定的场景中被Spring
回调,并传入对应的参数供Bean
使用。
BeanNameAware
setBeanName
该方法在Bean
实例化完成并注入属性后,BeanPostProcessor#postProcessBeforeInitialization
方法前被调用。
Bean
的名称将会从入参中被传入,该name可能会被添加例如#
之类的前缀标识符,如果想要获得原始的name,可以调用BeanFactoryUtils#originalBeanName(String)
。
BeanClassLoaderAware
setBeanClassLoader
该方法在Bean
实例化完成并注入属性后,BeanPostProcessor#postProcessBeforeInitialization
方法前被调用。
Bean
的classLoader
将会被传入。
BeanFactoryAware
setBeanFactory
该方法在Bean
实例化完成并注入属性后,BeanPostProcessor#postProcessBeforeInitialization
方法前被调用。
持有当前Bean
的BeanFactory
将会被传入。
EnvironmentAware
setEnvironment
该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization
调用,即在Bean
实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSet
和init-method
。
将从入参传入Environment
EmbeddedValueResolverAware
setEmbeddedValueResolver
该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization
调用,即在Bean
实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSet
和init-method
。
将从入参传入StringValueResolver
ResourceLoaderAware
setResourceLoader
该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization
调用,即在Bean
实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSet
和init-method
。
将从入参传入ResourceLoader
ApplicationEventPublisherAware
setApplicationEventPublisher
该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization
调用,即在Bean
实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSet
和init-method
。
将从入参传入ApplicationEventPublisher
MessageSourceAware
setMessageSource
该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization
调用,即在Bean
实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSet
和init-method
。
将从入参传入MessageSource
ApplicationContextAware
setApplicationContext
该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization
调用,即在Bean
实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSet
和init-method
。
将从入参传入ApplicationContext
Other
FactoryBean
1 | public interface FactoryBean<T> { |
FactoryBean
是一个定义工厂Bean
的接口,如果一个Bean
实现了这个接口,那么Spring
在初始化的时候会创建该类型的实例,在通过该实例创建其对应的Bean
。
FactoryBean
有三个方法需要子类来实现
isSingleton
方法用来返回当前FactoryBean
创建的Bean
是否为单例,如果返回true
表示是单例(singleton
)模式的Bean
,如果返回false
,表示是原型模式(prototype
)的Bean
。
getObjectType
方法用来返回该FactoryBean
将会创建的Bean
的类型。
getObject
方法返回创建的Bean
,当Spring
需要通过FactoryBean
创建一个新的Bean
的时候,将会调用FactoryBean#getObject
来获取Bean
并放入IOC
容器中。
AbstractFactoryBean
AbstractFactoryBean
继承自FactoryBean
,提供了getObject
方法的默认实现并添加了两个抽象方法需要子类实现。一般情况下,AbstractFactoryBean
需要实现四个方法
isSingleton
与FactoryBean
中的isSingleton
方法相同。
getObjectType
与FactoryBean
中的getObjectType
方法相同。
createInstance
与FactoryBean
中的createInstance
方法相同,即AbstractFactoryBean
中不需要实现createInstance
方法。
destroyInstance
方法将在Bean
被销毁前调用,用来手动处理Bean
销毁前需要处理的工作,例如关闭资源等。
InitializingBean
1 | public interface InitializingBean { |
实现了InitializingBean
的Bean
将在实例化完成后被回调,具体时机是Bean
属性注入完成、BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
三类Aware
回调完成、BeanPostProcessor#postProcessBeforeInitialization
调用完成之后,BeanPostProcessor#postProcessAfterInitialization
之前。
此时,Bean
已经基本初始化完成,此时可以在此方法内部做诸如参数校验、最终初始化等操作。
DisposableBean
1 | public interface DisposableBean { |
实现了DisposableBean
的Bean
将在销毁前被回调。
可以在该方法内部做最后的清理工作,例如关闭资源等。
ApplicationRunner
1 | public interface ApplicationRunner { |
Spring
将在刷新完上下文之后,依次调用所有实现了ApplicationRunner
接口Bean
的’run’方法。
CommandLineRunner
1 | public interface CommandLineRunner { |
Spring
将在刷新完上下文之后,依次调用所有实现了CommandLineRunner
接口Bean
的run
方法,与ApplicationRunner
的差别是CommandLineRunner
会将启动命令行中的参数传入run
方法。
ApplicationListener
1 | public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { |
实现ApplicationListener
的Bean
将在对应ApplicationEvent
事件发生时被回调,对应的事件为ApplicationListener
定义的类型参数,可以通过@EventListener
实现类似效果。
可以通过ApplicationEventPublisher#publishEvent
发布消息
Lifecycle
1 | public interface Lifecycle { |
实现了Lifecycle
接口的Bean
,容器会在生命周期中的不同阶段回调对应的方法,可以在这些方法中执行特定的操作。
start
会在容器启动的最后阶段被调用,具体时机是创建完所有的Bean
之后,ContextRefreshedEvent
消息广播、调用ApplicationRunner#run
方法之前。一般情况下,Spring
容器不会调用start()方法,所以Lifecycle#start
不会被调用,所以需要使用SmartLifecycle
。
stop
会在容器关闭前被调用,具体时机是ContextClosedEvent
消息广播之后,DisposableBean#destory
方法调用之前。
isRunning
用来返回当前Bean
是否是运行中,如果返回true
,那么不会执行start
方法,会执行stop
方法;如果返回false
,那么会执行start
方法,不会执行stop
方法。
SmartLifecycle
SmartLifecycle
在Lifecycle
基础上实现了Phased
类,可以用来控制不同SmartLifecycle
的执行顺序,并且在容器进行刷新时也会调用start
方法。
ImportBeanDefinitionRegistrar
1 | public interface ImportBeanDefinitionRegistrar { |
该接口的作用类似与BeanDefinitionRegistryPostProcessor
,可以在此处修改已加载的BeanDefinition
,或添加自定义的BeanDefinition
,来实现动态注册Bean
;
不同于其他的组件只需要注入IOC
容器即可被自动发现并被调用,BeanDefinitionRegistryPostProcessor
子类需要通过@Import
注解引入方可使用。
registerBeanDefinitions
方法将会被ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
调用,ConfigurationClassPostProcessor
是通过实现了BeanDefinitionRegistryPostProcessor
接口而获得注册BeanDefinition
的能力,所以被调用时机与BeanDefinitionRegistryPostProcessor
一致。
各类接口调用时机
- BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
- BeanDefinitionRegistryPostProcessor#postProcessBeanFactory
- BeanFactoryPostProcessor#postProcessBeanFactory
- InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
- 创建
Bean
实例 - MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
- InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
- InstantiationAwareBeanPostProcessor#postProcessPropertyValues
Bean
属性注入- BeanNameAware#setBeanName
- BeanClassLoaderAware#setBeanClassLoader
- BeanFactoryAware#setBeanFactory
- BeanPostProcessor#postProcessBeforeInitialization
- InitializingBean#afterPropertiesSet
- 执行
init-method
- BeanPostProcessor#postProcessAfterInitialization
- Lifecycle#start
- ApplicationRunner#run
- CommandLineRunner#run
- 广播ContextRefreshedEvent