• 【SpringBoot】浅谈向容器注入Bean有几种方式。


    前言

    SpringBoot的核心之一是通过IOC容器管理各个bean对象,前几天看到一个大厂面试题问向Spring容器中注入bean有哪几种方式,今天整理了下跟大家分析一波。

    这个题看似简单,实则暗藏玄机,可能大部分掘友能回答出一部分,要回答全面在众多面试者中脱颖而出似乎不是那么简单。

    首先面试官问出这个问题,思路应该要立刻转到SpringBoot的启动流程来,按SpringBoot是怎么扫描出要注入的类入手。

    启动流程模糊的掘友可以回顾下之前的文章:SpringBoot启动流程

    @Component + @ComponentScan

    SpringBoot启动类的@SpringBootApplication注解中就标注了 @ComponentScan注解,这个注解默认扫描当前包及其子包下的标注有@Component@Controller@Service@Repository等的类加载到容器中。

    这一条应该都能答出来,属于基础八股了。

    @Import注解

    了解过SpringBoot源码的掘友应该对这个注解不陌生,SpringBoot之所以拥有自动装配能力,全依仗于启动类@SpringBootApplication注解中的另一个核心注解 @EnableAutoConfiguration

    点进去这个注解会发现 @Import(AutoConfigurationImportSelector.class),也就是通过将AutoConfigurationImportSelector类加载到容器中。

    并通过此类的getAutoConfigurationEntry()方法,查找并筛选出位于META-INF/spring.factories文件中的所有需要注入的自动配置类并加载。

    这个注解也可以直接注入class,SpringBoot默认是注入ImportSelector接口,重写selectImports规则实现,本质上都是将外部类加载到当前classpath中并注入成bean。

    @Configuration + @Bean

    这个组合相信大家都有用过,比如想利用ioc容器管理一个map容器,只需要在配置类上标注上@Configuration声明配置类,在某个方法上标注@Bean并返回一个new HashMap即可。

    @Configuration
    public class TestConfig {
    
       @Bean
       public Map TestAutoMap() {
           return new HashMap();
       }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    BeanDefinitionRegistryPostProcessor

    万变不离其宗,掌握SpringBoot启动流程和SpringBean的生命周期,很多问题就能连点成线的串起来。

    我们知道SpringBean的生命周期中有很多前后置方法,整体上可以概括为普通类对象转化为beanDefinition再转化为spring中的bean这么三个阶段。

    而Spring会在启动的AbstratApplicationContxt类中的refresh方法中执行 invokeBeanFactoryPostProcessors,这个方法中会回调所有实现 BeanDefinitionRegistryPostProcessor接口的钩子方法。

    可以简单理解成beanDefinition加载完毕之后,会对beanDefinition进行后置处理。所以理论上实现BeanDefinitionRegistryPostProcessor接口就可以手动将bean注入到容器中。

    public class TestBeanProcessor {
    
       public static void main(String[] args) {
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
          UptownBeanProcessor beanDefinitionRegistryPostProcessor = new UptownBeanProcessor();
          applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);
          applicationContext.refresh();
          Object bean = applicationContext.getBean("test_map");
          System.out.println(bean);
       }
    }
    
    
    class UptownBeanProcessor implements BeanDefinitionRegistryPostProcessor {
    
       @Override
       public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
          AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(HashMap.class).getBeanDefinition();
          registry.registerBeanDefinition("test_map", beanDefinition);
       }
    
       @Override
       public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    总结

    • 按照SpringBoot启动原理和SpringBean的生命周期为思路
    • @Component + @ComponentScan
    • @Bean + @Configuration
    • @Import
    • BeanDefinitionRegistryPostProcessor接口实现postProcessBeanDefinitionRegistry后置函数
  • 相关阅读:
    【论文阅读】提升的自动作文评分通过Prompt预测和匹配
    3.JS数组求和的几种方法
    数仓项目拉链表
    深度解析:会用Excel,还有必要学Python吗?
    华为OD机试真题-学生重新排队-2024年OD统一考试(C卷)
    黑马QtDay2学习笔记:
    一文看懂推荐系统:经典双塔模型:微软DSSM模型(Deep Structured Semantic Models),无特征交互,后来美团改进了
    满帮web页面首屏秒开解决之道
    DSPE-PEG-Aldehyde,DSPE-PEG-CHO科学研究用化学试剂
    Linux系统安全与应用【一】
  • 原文地址:https://blog.csdn.net/m0_37817220/article/details/128207760