ApplicationContextInitializer

news/2025/3/14 18:20:37/

目录

  • 在何处执行?
  • 何时初始化?
    • 自己写一个ApplicationContextInitializer
  • 那这个类的设计具体有什么作用呢??
    • 1. DelegatingApplicationContextInitializer
    • 2. SharedMetadataReaderFactoryContextInitializer
    • 3. ContextIdApplicationContextInitializer
    • 4. ConfigurationWarningsApplicationContextInitializer
    • 5. RSocketPortInfoApplicationContextInitializer
    • 6. ServerPoerInfoApplicationContextInitializer
    • 7. ConditionEvaluationReportLoggingListener
  • 总结

在何处执行?

执行时机在SpringApplication类的prepareContenxt中,在run方法中可以找到prepareContext方法。

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {...// 执行applyInitializersapplyInitializers(context);...
}protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),ApplicationContextInitializer.class);Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");initializer.initialize(context);}
}

何时初始化?

在SpringApplication构造函数中会初始化initializers。

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {...// 初始化initializerssetInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));...
}private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {return getSpringFactoriesInstances(type, new Class<?>[] {});
}private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = getClassLoader();// 在META-INF/spring.factories中寻找实现类。Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;
}

自己写一个ApplicationContextInitializer

public class OrangeInitializer implements ApplicationContextInitializer {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("my initializer");}
}

在resources的META-INF中创建一个spring.factories文件,下面是我的例子,具体的路径还是看自己的。

org.springframework.context.ApplicationContextInitializer=\com.example.spring.spring.listener.OrangeInitializer

可以看到启动SpringBoot之后,my initializer打印出来了。
在这里插入图片描述

那这个类的设计具体有什么作用呢??

想要知道这里类的作用,切入点就是看看它的实现类都干了什么事情,下面八个类,有一个OrangeInitializer是自定义的,其他七个是SpringBoot启动就有的。当然也可以从名称上去猜测,他就是用来初始化ApplicationContext的。看一下它的默认实现都干了什么事情!

在这里插入图片描述

1. DelegatingApplicationContextInitializer

private static final String PROPERTY_NAME = "context.initializer.classes";@Override
public void initialize(ConfigurableApplicationContext context) {ConfigurableEnvironment environment = context.getEnvironment();// 获取对象List<Class<?>> initializerClasses = getInitializerClasses(environment);// 执行具体的ApplicationContextInitializerif (!initializerClasses.isEmpty()) {applyInitializerClasses(context, initializerClasses);}
}private List<Class<?>> getInitializerClasses(ConfigurableEnvironment env) {// 从Environment中拿context.initializer.classes。String classNames = env.getProperty(PROPERTY_NAME);List<Class<?>> classes = new ArrayList<>();if (StringUtils.hasLength(classNames)) {for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {classes.add(getInitializerClass(className));}}return classes;
}

通过配置文件去注入ApplicationContextInitializer。

public class EnvironmentInitializer implements ApplicationContextInitializer {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("my environmentInitializer");}
}

application.yml如果自己有多个类,可以用英文逗号隔开

context:initializer:classes: com.example.spring.spring.initializer.EnvironmentInitializer

在这里插入图片描述

2. SharedMetadataReaderFactoryContextInitializer

这个就简单多了,就把一个BeanFactoryPostProcessor放入到ConfigurableApplicationContext中,会在AbstractApplicationContext的refresh的invokeBeanFactoryPostProcessors去执行。

@Override
public void initialize(ConfigurableApplicationContext applicationContext) {BeanFactoryPostProcessor postProcessor = new CachingMetadataReaderFactoryPostProcessor(applicationContext);applicationContext.addBeanFactoryPostProcessor(postProcessor);
}

3. ContextIdApplicationContextInitializer

也不知道作用是啥。

@Override
public void initialize(ConfigurableApplicationContext applicationContext) {ContextId contextId = getContextId(applicationContext);applicationContext.setId(contextId.getId());applicationContext.getBeanFactory().registerSingleton(ContextId.class.getName(), contextId);
}

4. ConfigurationWarningsApplicationContextInitializer

也是添加一个BeanFactoryPostProcessor处理器。

@Override
public void initialize(ConfigurableApplicationContext context) {context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
}

5. RSocketPortInfoApplicationContextInitializer

不知道是干什么的

6. ServerPoerInfoApplicationContextInitializer

7. ConditionEvaluationReportLoggingListener

不知道

@Override
public void initialize(ConfigurableApplicationContext applicationContext) {this.applicationContext = applicationContext;applicationContext.addApplicationListener(new ConditionEvaluationReportListener());if (applicationContext instanceof GenericApplicationContext) {// Get the report early in case the context fails to loadthis.report = ConditionEvaluationReport.get(this.applicationContext.getBeanFactory());}
}

总结

  1. ApplicationContextInitializer是用来填充ApplicationContext各种属性的
  2. 在refresh之前执行
  3. 有spring.factories / application.yml两种方法进行自定义扩展

http://www.ppmy.cn/news/1019714.html

相关文章

Android模板设计模式之 - 构建整个应用的BaseActivity

1. 模式介绍 模式的定义 定义一个操作中的算法的框架&#xff0c;而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 模式的使用场景 1.多个子类有公有的方法&#xff0c;并且逻辑基本相同时。 2.重要、复杂的算法&#xff0c;可…

Windows 7 CDC 串口驱动,GD32

Windows 7 自带 CDC 串口类设备的驱动程序文件 usbser.sys&#xff0c;所缺的是驱动配置文件 usbser.inf 文件&#xff0c;将 Windows 10 的 usbser.inf 文件拷贝到 Windows 7&#xff0c;注释掉 SourceDisksNames 和 SourceDisksFiles 部分就可以作为 Windows 7 的 CDC 串口类…

恒运资本:股票印花税下降有什么影响?什么原因导致下降?

在进行股票教育过程中是需求收取必定的手续费的&#xff0c;比如说买卖佣钱、印花税、过户费等等。那么股票印花税下降有什么影响&#xff1f;什么原因导致下降&#xff1f;下面就由恒运资本为大家剖析&#xff1a; 股票印花税下降有什么影响&#xff1f; 1、对于企业&#xf…

日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理

日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理 目录 日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理 1、在线Json &#xff0c;可以在线进行json 格式验证&#xff0c;解析转义等操作 2、Gif动图分解&#xff0c;在线把 gif 图分解成一张张单图 3、在线P…

多进程并发服务器

文章目录 思路问题多进程并发回环服务器代码客户端代码 思路 每当一个客户端连接服务器后&#xff0c;创建一个子进程负责与该客户端通信&#xff0c;客户端断开连接之后&#xff0c;服务器回收子进程资源。 问题 问题1&#xff1a;父进程阻塞在等待连接(accept())处&#xf…

考研C语言进阶题库——更新26-30题

目录 26.一个正整数&#xff0c;如果等于组成它的各个数字的阶数之和&#xff0c;该整数称为阶乘合数&#xff0c;例如1451阶加四阶加五阶&#xff0c;则145是一个三位阶乘合数&#xff0c;输入一个数&#xff0c;问共有多少个阶乘合数&#xff1f;(十万之内) 27.与2相关的数…

前端先行模拟接口(mock+expres+json)

目录 mock模拟数据&#xff1a;data/static.js 路由&#xff1a;index.js 服务器&#xff1a;server.js yarn /node 启动服务器&#xff1a;yarn start 客户端&#xff1a;修改代理路径(修改设置后都要重启才生效) 示例 后端框架express构建服务器 前端发起请求 静态数…

【EI/SCOPUS检索】第三届新媒体发展与现代化教育国际学术会议(NMDME 2023)

第三届新媒体发展与现代化教育国际学术会议&#xff08;NMDME 2023&#xff09; The 3rd International Conference on New Media Development and Modernized Education 第三届新媒体发展与现代化教育国际学术会议(NMDME 2023)将于2023年10月13-15日于西安召开。会议旨在为新…