SpringContext钩子函数
- 1、Aware 接口
- 2、InitializingBean
- 3、BeanPostProcessor
- 4、BeanFactoryPostProcessor
- 5、ImportSelector
- 6、ImportBeanDefinitionRegistrar
- 7、FactoryBean
- 8、ApplicationListener
- 9、BeanDefinitionRegistryPostProcessor
- 10、InstantiationAwareBeanPostProcessor
- 11、SmartInstantiationAwareBeanPostProcessor
- 12、MergedBeanDefinitionPostProcessor
Spring 提供了非常多的扩展接口,官方将这些接口称之为钩子,这些钩子会在特定的时间被回调,以此来增强 Spring 功能,可以通过这些钩子来实现各种需要的功能。
1、Aware 接口
Aware 从字面意思理解就是知道、感知的意思,是用来获取 Spring 内部对象的接口。Aware 自身是一个顶级接口,它有一系列子接口,在一个 Bean 中实现这些子接口并重写里面的 set 方法后,Spring 容器启动时,就会回调该 set 方法,而相应的对象会通过方法参数传递进去。我们以其中的 ApplicationContextAware 接口为例。
public class Test implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
在 Spring 启动过程中,会回调 setApplicationContext 方法,并传入 ApplicationContext 对象,之后就可对该对象进行操作。
以下是几种常用的 Aware 接口:
- BeanFactoryAware:获取 BeanFactory 对象,它是基础的容器接口。
- BeanNameAware:获取 Bean 的名称。
- EnvironmentAware:获取 Environment 对象,它表示整个的运行时环境,可以设置和获取配置属性。
- ApplicationEventPublisherAware:获取 ApplicationEventPublisher对象,它是用来发布事件的。
- ResourceLoaderAware:获取 ResourceLoader 对象,它是获取资源的工具。
2、InitializingBean
InitializingBean 是一个可以在 Bean 的生命周期执行自定义操作的接口,凡是实现该接口的 Bean,在初始化阶段都可以执行自定义的操作。
从 InitializingBean 源码中可以看出它有一个 afterPropertiesSet 方法,当一个 Bean 实现该接口时,在 Bean 的初始化阶段,会回调 afterPropertiesSet 方法,其初始化阶段具体指 Bean 设置完属性之后。
该接口使用方式如下:
@Component
public class Test implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Test 执行初始化");
}
}
3、BeanPostProcessor
BeanPostProcessor 和 InitializingBean 有点类似,也是可以在 Bean 的生命周期执行自定义操作,一般称之为 Bean 的后置处理器,不同的是,BeanPostProcessor 可以在 Bean 初始化前、后执行自定义操作,且针对的目标也不同,InitializingBean 针对的是实现 InitializingBean 接口的 Bean,而 BeanPostProcessor 针对的是所有的 Bean。
public interface BeanPostProcessor {
// Bean 初始化前调用
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// Bean 初始化后调用
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
BeanPostProcessor 的继承接口主要有:
- InstantiationAwareBeanPostProcessor
- MergedBeanDefinitionPostProcessor
- MergedBeanDefinitionPostProcessor
提供在Spring创建Bean的不同时期的钩子函数作用
4、BeanFactoryPostProcessor
BeanFactoryPostProcessor 是 Bean 工厂的后置处理器,一般用来修改上下文中的 BeanDefinition,修改 Bean 的属性值。
public interface BeanFactoryPostProcessor {
// 入参是一个 Bean 工厂:ConfigurableListableBeanFactory。该方法执行时,所有 BeanDefinition 都已被加载,但还未实例化 Bean。
// 可以对其进行覆盖或添加属性,甚至可以用于初始化 Bean。
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BeanFactoryPostProcessor 源码非常简单,其提供了一个 postProcessBeanFactory 方法,当所有的 BeanDefinition 被加载时,该方法会被回调。值得注意的是,Spring 内置了许多 BeanFactoryPostProcessor 的实现,以此来完善自身功能。
这里,我们来实现一个自定义的 BeanFactoryPostProcessor:
@Component
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String beanNames[] = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
System.out.println(beanDefinition);
}
}
}
5、ImportSelector
ImportSelector 是一个较为重要的扩展接口,通过该接口可动态的返回需要被容器管理的类,不过一般用来返回外部的配置类。可在标注 @Configuration 注解的类中,通过 @Import 导入 ImportSelector 来使用。
public interface ImportSelector {
// 方法入参是注解的元数据对象,返回值是类的全路径名数组
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
selectImports 方法返回的是类的全路径名。
自定义 ImportSelector:
public class TestImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
if (importingClassMetadata.hasAnnotation("")) {
// 判断是否包含某个注解
}
// 返回 Test 的全路径名,Test 会被放入到 Spring 容器中
return new String[]{"com.loong.diveinspringboot.test.Test"};
}
}
6、ImportBeanDefinitionRegistrar
该接口和 ImportSelector 类似,也是配合 @Import 使用,不过 ImportBeanDefinitionRegistrar 更为直接一点,它可以直接把 Bean 注册到容器中。
public interface ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
入参除了注解元数据对象 AnnotationMetadata 外,还多了一个 BeanDefinitionRegistry 对象。
自定义 ImportBeanDefinitionRegistrar:
public class TestRegistrar implements ImportBeanDefinitionRegistrar {
// 一般通过 AnnotationMetadata 进行业务判断,然后通过 BeanDefinitionRegistry 直接注册 Bean
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(Test.class);
beanDefinition.setLazyInit(true);
registry.registerBeanDefinition(Test.class.getName(), beanDefinition);
}
}
7、FactoryBean
FactoryBean 也是一种 Bean,不同于普通的 Bean,它是用来创建 Bean 实例的,属于工厂 Bean,不过它和普通的创建不同,它提供了更为灵活的方式,其实现有点类似于设计模式中的工厂模式和修饰器模式。
Spring 框架内置了许多 FactoryBean 的实现,它们在很多应用如(Spring的AOP、ORM、事务管理)及与其它第三框架(ehCache)集成时都有体现。
public interface FactoryBean<T> {
// 该方法会返回该 FactoryBean “生产”的对象实例,我们需要实现该方法以给出自己的对象实例化逻辑
T getObject() throws Exception;
// Bean的类型
Class<?> getObjectType();
// 是否是单例
default boolean isSingleton() {
return true;
}
}
8、ApplicationListener
ApplicationListener 是 Spring 实现事件机制的核心接口,属于观察者设计模式,一般配合 ApplicationEvent 使用。在 Spring 容器启动过程中,会在相应的阶段通过 ApplicationContext 发布 ApplicationEvent 事件,之后所有的 ApplicationListener 会被回调,根据事件类型,执行不同的操作。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
在 onApplicationEvent 方法中,通过 instanceof 判断 event 的事件类型。
自定义 ApplicationListener:
@Component
public class TestApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof TestApplicationEvent) {
TestApplicationEvent testApplicationEvent = (TestApplicationEvent) event;
System.out.println(testApplicationEvent.getName());
}
}
}
Spring 的许多核心功能也是通过其内置的钩子接口来实现的,特别是一些核心注解
9、BeanDefinitionRegistryPostProcessor
10、InstantiationAwareBeanPostProcessor
对象创建前调一次,给机会提前创建。 对象创建,没填充属性时调一次
11、SmartInstantiationAwareBeanPostProcessor
获取构造函数、获取早期Bean
12、MergedBeanDefinitionPostProcessor
构造函数创建后调用