https://juejin.cn/post/6999603401239576583
highlight: androidstudio
前言 :
Spring 的扩展点 是Spring易扩展的一个重要体现,熟悉这些扩展点的定义方式,以及其调用时机,可以在我们开发过程中游刃有余,进行各种骚操作。我个人觉得熟悉他们 并知道其原理,是非常有必要的,今天我们就一个个来看下。
本文总结出10个扩展点,如有遗漏,欢迎补充~
- 本文示例代码均已经上传到github
地址
: https://github.com/598572/xzll/tree/main/study-admin/study-admin-service/src/main/java/com/xzll/test/point
扩展点1
实现 ApplicationContextInitializer的initialize方法
- 时机 : spring容器还没被刷新之前 准备阶段 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); 此时所有的配置文件都已经加载
/**
* ApplicationContextInitializer扩展点演示 时机: spring容器还没被刷新之前
*
* <p>
* 因为这时候spring容器还没被刷新,所以想要自己的扩展的生效,有以下三种方式:
* <p>
* 1.在启动类中用springApplication.addInitializers(new ApplicationContextInitializerPoint())语句加入
* 2.配置文件配置context.initializer.classes=com.xzll.test.ApplicationContextInitializerPoint
* 3.Spring SPI扩展,在spring.factories中加入org.springframework.context.ApplicationContextInitializer=com.xzll.test.ApplicationContextInitializerPoint
* <p>
* //TODO 目前我试了三种方式 只有第二种方式可以输出该类的打印语句 ,1和2都没有输出打印语句 目前不知原因为何。留作以后研究吧
*
* 这是整个spring容器在刷新之前初始化ConfigurableApplicationContext的回调接口,简单来说,就是在容器刷新之前调用此类的initialize方法。
* 这个点允许被用户自己扩展。用户可以在整个spring容器还没被初始化之前做一些事情。
* 可以想到的场景可能为,在最开始激活一些配置,或者利用这时候class还没被类加载器加载的时机,进行动态字节码注入等操作。
*/
public class ApplicationContextInitializerPoint implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
// System.out.println("applicationContext: "+ JSON.toJSONString(applicationContext));
// 注意这里引入不了FastJson 会报错 AnnotationConfigApplicationContext has not been refreshed yet ; AnnotationConfigApplicationContext 尚未刷新
// 详见: https://stackoverflow.com/questions/28404817/annotationconfigapplicationcontext-has-not-been-refreshed-yet-whats-wrong
System.out.println("------------ApplicationContextInitializerPoint # initialize 开始-------------");
System.out.println("[ApplicationContextInitializer扩展点演示] # initialize: " + applicationContext.toString());
System.out.println("BeanDefinitionCount count: " + applicationContext.getBeanDefinitionCount());
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
Iterator<String> beanNamesIterator = beanFactory.getBeanNamesIterator();
beanNamesIterator.forEachRemaining(System.out::println);
System.out.println("时机: "+ "run 方法中的 this.prepareContext(); 的时候");
System.out.println("-------------ApplicationContextInitializerPoint # initialize 结束------------");
System.out.println();
}
/*
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
this.applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
this.load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
protected void applyInitializers(ConfigurableApplicationContext context) {
Iterator var2 = this.getInitializers().iterator();
while(var2.hasNext()) {
ApplicationContextInitializer initializer = (ApplicationContextInitializer)var2.next();
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);// todo 此处回调 initialize 方法
}
}
*/
}
扩展点2
实现 BeanDefinitionRegistryPostProcessor或BeanFactoryPostProcessor 的 postProcessBeanDefinitionRegistry 和 postProcessBeanFactory方法
- 时机: refresh()的 this.invokeBeanFactoryPostProcessors(beanFactory);此时此bean的定义信息 都已经加载完毕 但是还没到实例化以及初始化阶段
@Component
public class BeanDefinitionRegistryPostProcessorPoint implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("-----------------------[BeanDefinitionRegistryPostProcessor扩展点演示] # postProcessBeanDefinitionRegistry 开始--------------------------------------");
System.out.println("[BeanDefinitionRegistryPostProcessor扩展点演示] # postProcessBeanDefinitionRegistry");
System.out.println("时机: refresh()的 this.invokeBeanFactoryPostProcessors(beanFactory); 方法中执行; " +
"此时 bean的定义信息 都已经加载完毕 但是还没到实例化以及初始化阶段");
System.out.println("-----------------------[BeanDefinitionRegistryPostProcessor扩展点演示] # postProcessBeanDefinitionRegistry 结束--------------------------------------");
System.out.println();
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("-----------------------[BeanDefinitionRegistryPostProcessor扩展点演示] # postProcessBeanFactory 开始--------------------------------------");
System.out.println("[BeanDefinitionRegistryPostProcessor扩展点演示] # postProcessBeanFactory");
System.out.println("时机: refresh()的 this.invokeBeanFactoryPostProcessors(beanFactory); 方法中执行; " +
"此时 bean的定义信息 都已经加载完毕 但是还没到实例化以及初始化阶段");
System.out.println("-----------------------[BeanDefinitionRegistryPostProcessor扩展点演示] # postProcessBeanFactory 结束--------------------------------------");
System.out.println();
}
}
@Component
public class BeanFactoryPostProcessorPoint implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("-----------------------[BeanFactoryPostProcessor扩展点演示] # postProcessBeanFactory 开始--------------------------------------");
System.out.println("[BeanFactoryPostProcessor扩展点演示] # postProcessBeanFactory");
System.out.println("时机: refresh()的 this.invokeBeanFactoryPostProcessors(beanFactory); 方法中执行; " +
"此时 bean的定义信息 都已经加载完毕 但是还没到实例化以及初始化阶段");
System.out.println("-----------------------[BeanFactoryPostProcessor扩展点演示] # postProcessBeanFactory 结束--------------------------------------");
System.out.println();
}
}
扩展点3
实现 BeanPostProcessor 的 postProcessBeforeInitialization 或postProcessAfterInitialization方法
时机: bean在初始化之前(postProcessBeforeInitialization) 和初始化之后(postProcessAfterInitialization),注意 初始化前说明其肯定已经实例化了
@Configuration
public class BeanPostProcessPoint implements BeanPostProcessor {
public BeanPostProcessPoint() {
System.out.println();
System.out.println("################## BeanPostProcessPoint 的构造方法 ##################");
System.out.println();
}
/**
* bean初始化之前
*
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
/**
* 可以根据需要在这里进行某个bean的扩展
*/
if (bean instanceof TestController) {
System.out.println("-----------------------[BeanPostProcessPoint] 扩展点演示 # postProcessBeforeInitialization 开始--------------------------------------");
System.out.println("[BeanPostProcessPoint] 扩展点演示 # postProcessBeforeInitialization , crurrentBeanName: " + beanName);