springboot源码解析-系统初始化器

系统初始化器ApplicationContextInitializer

官方对其描述是 Spring容器刷新之前执行的一个回调函数,它的作用是向 Springboot容器中注册属性

案例:通过系统初始化器向springboot容器中注入属性的方法。

方法1:
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
   @Override
   public void initialize(ConfigurableApplicationContext applicationContext) {
      // 获取环境变量
      ConfigurableEnvironment environment = applicationContext.getEnvironment();
      // 自定义一个属性
      Map<String,Object> map = new HashMap<>();
      map.put("key1","value1");
      MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer",map);
      //加入到环境变量的属性中
      environment.getPropertySources().addLast(mapPropertySource);
      System.out.println("run 第一个初始化器,向springboot容器中注入属性");
   }
}

之后,在resources下新建一个META-INF文件夹,放入一个spring.factories(配置文件)(自动装载机制)

org.springframework.context.ApplicationContextInitializer=\
com.example.springbootlearn.initializer.FirstInitializer

验证,新建一个service

@Service
public class TestService implements ApplicationContextAware {
   private ApplicationContext applicationContext;
   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      this.applicationContext= applicationContext;
   }

   public String test(){
      return applicationContext.getEnvironment().getProperty("key1");
   }
}

新建一个controller

@RestController
public class HelloController {

   @Resource
   private TestService testService;

   @GetMapping("test")
   public String getname(){
      return testService.test();
   }
}

访问http://127.0.0.1:8080/test 就可以将我们注入的属性打印出来value1.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.6)
run 第一个初始化器,向springboot容器中注入属性
方法2:

建SecondInitializer

@Order(2)
public class SecondInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
   @Override
   public void initialize(ConfigurableApplicationContext applicationContext) {
      // 获取环境变量
      ConfigurableEnvironment environment = applicationContext.getEnvironment();
      // 自定义一个属性
      Map<String,Object> map = new HashMap<>();
      map.put("key2","value2");
      MapPropertySource mapPropertySource = new MapPropertySource("secondInitializer",map);
      //加入到环境变量的属性中
      environment.getPropertySources().addLast(mapPropertySource);
      System.out.println("run 第二个初始化器,向springboot容器中注入属性");
   }
}

然后在启动类上改进

@SpringBootApplication
public class SpringbootlearnApplication {

   public static void main(String[] args) {
      // SpringApplication.run(SpringbootlearnApplication.class, args);

      SpringApplication springApplication = new SpringApplication(SpringbootlearnApplication.class);
      springApplication.addInitializers(new SecondInitializer());
      springApplication.run(args);
   }
}

启动后控制台打印:

run 第一个初始化器,向springboot容器中注入属性
run 第二个初始化器,向springboot容器中注入属性

debug断点applicationContext.getEnvironment().getProperty(“key2”);结果value2

方法3:

通过配置

@Order(3)
public class ThirdInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
   @Override
   public void initialize(ConfigurableApplicationContext applicationContext) {
      // 获取环境变量
      ConfigurableEnvironment environment = applicationContext.getEnvironment();
      // 自定义一个属性
      Map<String,Object> map = new HashMap<>();
      map.put("key3","value3");
      MapPropertySource mapPropertySource = new MapPropertySource("thirdInitializer",map);
      //加入到环境变量的属性中
      environment.getPropertySources().addLast(mapPropertySource);
      System.out.println("run 第三个初始化器,向springboot容器中注入属性");
   }
}

Application.yml

context:
  initializer:
    classes: com.example.springbootlearn.initializer.ThirdInitializer

启动:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.6)

run 第三个初始化器,向springboot容器中注入属性
run 第一个初始化器,向springboot容器中注入属性
run 第二个初始化器,向springboot容器中注入属性

@order值越小越靠前,但是,第三个初始化器,是放入配置文件中,所以优先打印。

以上三种实现方式:都是通过实现ApplicationContextInitializer接口

只不过后续不同,第一个是通过自动装配spring.factories实现,第二个是主启动类设置进去,第三个是配置文件实现(也可以理解为自动装配。

工厂加载机制SpringFactoriesLoader

它的意思是:

  • 框架内部使用通用工厂加载机制(工厂模式)
  • 从classpath下多个jar读取文件并初始化类(从各个jar中的META-INF/spring.factories)
  • 文件是内容是k-v形式,Properties(内部是hashtable)类型
  • key是全限定名(接口,抽象类),value是具体实现,如果是多个实现则用逗号分割。
    • example.MyService=example.MyServiceImpl1,example.MyServiceImpl2
      其中example.MyService是接口的名称(key), MyServiceImpl1和MyServiceImpl2是两个实现(value)。

初始化器是如何被springboot发现的?

debug断点,

在这里插入图片描述
在这里插入图片描述
SpringFactoriesLoader.loadFactoryNames

使用给定的类加载器从"META-INF/spring.factories"加载给定类型的工厂实现的完全限定类名。
在这里插入图片描述
setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class))的含义就是:
含义就是从spring.factories中key=ApplicationContextInitializer,找到所对应的value值,并将查到的所有全类名实例化,并最后放入到list集合中。

分析方法1的方式

由于方法1它是有spring.factories配置,所以,肯定能加载成功。

方法2的方式:

springApplication.addInitializers(new SecondInitializer());

也可以加载成功

方法3的方式:DelegatingApplicationContextInitializer
在这里插入图片描述
在这里插入图片描述

一句话总结就是:SpringFactoriesLoader将spring.factories下的所有文件加载出来,并且全部实例化放入一个list集合中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值