Spring
提供了非常多的钩子方法和钩子接口,善用它们可以极大地方便我们开发,本篇文章将会详细介绍各种钩子方法和钩子接口的使用方式。
Aware接口
Spring中提供了各种Aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有: BeanFactoryAware
,BeanNameAware
,ApplicationContextAware
,EnvironmentAware
,BeanClassLoaderAware
等,这些Aware
的作用都可以从命名得知,并且其使用也是十分简单。
接口名 | 描述 |
---|---|
ApplicationContextAware |
实现了这个接口的类都可以获取到一个 ApplicationContext 对象. 可以获取容器中的所有Bean 。 |
ApplicationEventPublisherAware |
在bean 中可以得到应用上下文的事件发布器, 从而可以在Bean 中发布应用上下文的事件。 |
BeanClassLoaderAware |
获取bean 的类加载器 |
BeanFactoryAware |
获取bean 的工厂 |
BeanNameAware |
获取bean 在容器中的名字 |
BootstrapContextAware |
获取BootstrapContext |
LoadTimeWeaverAware |
加载Spring Bean 时织入第三方模块, 如AspectJ |
MessageSourceAware |
主要用于获取国际化相关接口 |
NotificationPublisherAware |
用于获取通知发布者 |
ResourceLoaderAware |
初始化时注入ResourceLoader |
ServletConfigAware |
web开发过程中获取ServletConfig |
ServletContextAware |
web开发过程中获取ServletContext 信息 |
EnvironmentAware |
获取当前的应用的环境,从而用来获取配置信息、当前profile 等信息 |
EmbeddedValueResolverAware |
获取StringValueResolver ,用来解析 ${app.test} 的字符串值。 |
InitializingBean接口和DisposableBean接口
InitializingBean
接口只有一个方法#afterPropertiesSet
:当一个Bean实现InitializingBean
,#afterPropertiesSet
方法里面可以添加自定义的初始化方法或者做一些资源初始化操作。当BeanFactory
设置完所有的Bean属性之后才会调用#afterPropertiesSet
方法DisposableBean
接口只有一个方法#destroy
:当一个单例Bean实现DisposableBean
,#destroy
可以添加自定义的一些销毁方法或者资源释放操作。
使用示例:
1 |
|
ImportBeanDefinitionRegistrar接口
当处理Java编程式配置类(使用了@Configuration的类)的时候,
ImportBeanDefinitionRegistrar
接口的实现类可以注册额外的bean definitions
。ImportBeanDefinitionRegistrar
接口的实现类必须提供给@Import
注解或者是ImportSelector
接口返回值。ImportBeanDefinitionRegistrar
接口的实现类可能还会实现下面org.springframework.beans.factory.Aware
接口中的一个或者多个,它们各自的方法优先于ImportBeanDefinitionRegistrar#registerBeanDefinitions
被调用。org.springframework.context.EnvironmentAware
(读取或者修改Environment的变量)org.springframework.beans.factory.BeanFactoryAware
(获取Bean自身的Bean工厂)org.springframework.beans.factory.BeanClassLoaderAware
(获取Bean自身的类加载器)org.springframework.context.ResourceLoaderAware
(获取Bean自身的资源加载器)
BeanPostProcessor接口和BeanFactoryPostProcessor接口
一般我们叫这两个接口为Spring的Bean后置处理器接口,作用是为Bean的各个处理操作前后提供可扩展的空间。
BeanFactoryPostProcessor
1 | public interface BeanFactoryPostProcessor { |
在标准初始化之后修改应用程序上下文的内部bean工厂。 此时所有bean定义都已经加载完成,但尚未实例化任何bean。 这允许覆盖或添加属性,甚至是初始化bean。
BeanPostProcessor
BeanPostProcessor接口是最顶层的接口,接口定义:
1 | public interface BeanPostProcessor { |
postProcessBeforeInitialization
是指bean在初始化之前需要调用的方法postProcessAfterInitialization
是指bean在初始化之后需要调用的方法postProcessBeforeInitialization
和postProcessAfterInitialization
方法被调用的时候。这个时候bean已经被实例化,并且所有该注入的属性都已经被注入,是一个完整的bean。
InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor
接口继承自BeanPostProcessor
接口。多出了3个方法:
1 | public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { |
postProcessBeforeInstantiation
方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object
,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization
方法会调用,其它方法不再调用。postProcessAfterInstantiation
方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null
。如果该方法返回false
,会忽略属性值的设置;如果返回true
,会按照正常流程设置属性值postProcessProperties
方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation
方法返回false
,该方法不会被调用。可以在该方法内对属性值进行修改。
SmartInstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor
接口继承InstantiationAwareBeanPostProcessor
接口。多出了3个方法:
1 | public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { |
predictBeanType
方法用于预测Bean的类型,返回第一个预测成功的Class
类型,如果不能预测返回null。主要在于BeanDefinition
无法确定Bean
类型的时候调用该方法来确定类型。determineCandidateConstructors
方法用于选择合适的构造器,比如类有多个构造器,可以实现这个方法选择合适的构造器并用于实例化对象。getEarlyBeanReference
主要用于解决循环引用问题。只有单例对象才会调用此方法。
DestructionAwareBeanPostProcessor
DestructionAwareBeanPostProcessor
接口继承BeanPostProcessor
接口。多出了2个方法:
1 | public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor { |
MergedBeanDefinitionPostProcessor
DestructionAwareBeanPostProcessor
接口继承BeanPostProcessor
接口。多出了2个方法:
1 | public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor { |
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor
接口可以看作是BeanFactoryPostProcessor
和ImportBeanDefinitionRegistrar
的功能集合,既可以获取和修改BeanDefinition
的元数据,也可以实现BeanDefinition
的注册、移除等操作。
1 | public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { |
FactoryBean接口
首先第一眼要注意,是FactoryBean
接口而不是BeanFactory
接口。一般情况下,Spring通过反射机制利用bean
的class
属性指定实现类来实例化bean ,实例化bean过程比较复杂。FactoryBean
接口就是为了简化此过程,把bean
的实例化定制逻辑下发给使用者。
在该接口中还定义了以下3个方法。
T getObject()
:返回由FactoryBean
创建的bean实例,如果isSingleton()``返回true
,则该实例会放到Spring容器中单实例缓存池中。boolean isSingleton()
:返回由FactoryBean
创建的bean实例的作用域是singleton
还是prototype
。Class<T> getObjectType()
:返回FactoryBean
创建的bean
类型。
注意一点:通过Spring容器的getBean()
方法返回的不是FactoryBean
本身,而是FactoryBean#getObject()
方法所返回的对象,相当于FactoryBean#getObject()
代理了getBean()
方法。如果希望获取FactoryBean
的实例,则需要在使用getBean
(beanName) 方法时在beanName
前显示的加上 “&” 前缀。
ApplicationListener
ApplicationListener
是一个接口,里面只有一个onApplicationEvent(E event)
方法,这个泛型E
必须是ApplicationEvent
的子类,而ApplicationEvent
是Spring定义的事件,继承于EventObject
,构造要求必须传入一个Object
类型的source
,这个source
可以作为一个存储对象。将会在ApplicationListener
的onApplicationEvent
里面得到回调。如果在上下文中部署一个实现了ApplicationListener
接口的bean,那么每当在一个ApplicationEvent
发布到 ApplicationContext
时,这个bean
得到通知。其实这就是标准的Oberver
设计模式。另外,ApplicationEvent
的发布由ApplicationContext
通过#publishEvent
方法完成。其实这个实现从原理和代码上看都有点像Guava
的eventbus
。
贴一个例子:
EmailEvent:
1 |
|
EmailApplicationListener:
1 |
|
测试类:
1 | .class) (classes = Application |
原创不易,觉得文章写得不错的小伙伴,点个赞👍 鼓励一下吧~
欢迎关注我的开源项目:一款适用于SpringBoot的轻量级HTTP调用框架