• 【学习笔记】springBoot中获取sping管理的bean


    一、使用场景

    某些场景下,需要在某个普通的java类(非Spring框架管理)中使用Spring管理的bean,这个时候可以使用实现 ApplicationContextAware 的方式来获取目标bean.

    二、springBoot中获取sping管理的bean

    2.1 生成工具类SpringContextUtil

    写一个工具类SpringContextUtil,该类实现 ApplicationContextAware,通过 beanName、bean对应的Class、beanName+bean对应的Class 三种方式来获取目标bean,具体如下:

    package com.bigbear.test.utils;
    @Component
    @Slf4j
    public class SpringContextUtil implements ApplicationContextAware {
    
        private static ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            if (SpringContextUtil.applicationContext == null) {
                SpringContextUtil.applicationContext = applicationContext;
            }
            log.info("ApplicationContext配置成功,applicationContext对象:"+SpringContextUtil.applicationContext);
        }
    
        public static ApplicationContext  getApplicationContext(){
            return applicationContext;
        }
    
        /**
         * 通过beanName获取 Bean
         * @param beanName
         * @return
         */
        public static Object getBean(String beanName){
            return getApplicationContext().getBean(beanName);
        }
        /**
         * 通过class获取Bean
         * @param clazz
         * @return
         */
        public static <T> T getBean(Class<T> clazz) {
            return getApplicationContext().getBean(clazz);
        }
    
        /**
         * 通过beanName,以及Clazz返回指定的Bean
         * @param name
         * @param clazz
         * @param 
         * @return
         */
        public static <T> T getBean(String beanName, Class<T> clazz) {
            return getApplicationContext().getBean(beanName, clazz);
        }
    }
    
    • 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
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    1、实现ApplicationContextAware接口:Spring项目启动初始化的过程中,会有一个步骤执行ApplicationContextAware接口的实现类的setApplicationContext方法,这样我们就能拿到applicationContext信息,进而可以通过sprig上下文获取想要的bean。

    2、需要使用 @Component ,让spring能够扫描到该工具类;

    3、根据需求,可以通过 beanName 或 bean对应的class 获取目标bean;

    2.2 使用工具类SpringContextUtil

    这里有个被Spring管理的bean : myTestDemo

    @Service("myTestDemo")
    public class MyTestDemo {
    
        @Autowired
        private UserService userService;
        
        public String getPasswordByAppId(String loginName) {
            UserDo  userDo =  userService.findUserByLoginName(loginName);
            if(ObjectUtils.isEmpty(userDo) || StringUtils.isEmpty(userDo.getPassword())){
                return "";
            }
            return userDo.getPassword();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在另外一个java类中通过Spring上下文获取这个 “myTestDemo” bean,并用来生成一个对象:

    @Configuration
    public class ApiIdentificatorConfig {
    	@Bean("apiIdentificator")
        public ApiIdentificator getApiIdentificator(){
            // 获取Spring上下文
            ApplicationContext context = SpringContextUtil.getApplicationContext();
            //从Spring上下文中取出 myTestBean bean
            MyTestDemo myTestDemo = (MyTestDemo)context.getBean("myTestDemo");
            // myTestBean 是生成 apiIdentificator 对象 的构造参数
            return new DefaultApiIdentificatorImpl(myTestDemo);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.3 注意事项:getApplicationContext为Null问题

    在上述使用过程中可能会出现 “getApplicationContext为Null问题 ”,原因是Spring初始化过程中SpringContextUtil.setApplicationContext() 方法没有被执行,导致 applicationContext 没有获取到。

    解决办法:在SpringBoot启动类扫描的时候,该SpringContextUtil类必须优先执行类扫描。

    具体来说有两种解法:
    way1: 将 SpringContextUtil.java 这个类和springboot启动类放同一包下;
    way2: 更改springboot启动类的包扫描路径, 将该类放到第一个扫描的位置即可,如下:

    @SpringBootApplication(scanBasePackages = {"com.bigbear.test.utils","com.bigbear.test.*"})
    public class SpringBootHelloApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringBootHelloApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    三、参考文档

    1、spring boot获取spring容器中的bean对象:https://blog.csdn.net/qq_29235677/article/details/119652555
    2、spring启动流程的源码分析:https://blog.csdn.net/qq_29235677/article/details/118458990
    3、SpringApplication.run执行流程详解:https://blog.csdn.net/javaheheda/article/details/104963485

  • 相关阅读:
    目标检测YOLO实战应用案例100讲-基于YOLOv5的航拍图像旋转目标检测(下)
    【iOS】ViewController的生命周期
    LINUX-基础回顾
    郑卢高速洛阳至洛宁段路基路面综合设计K14+000-K15+400设计计算书+cad图纸
    C++--哈希表--散列--冲突--哈希闭散列模拟实现
    SpringBoot定时任务 - Spring自带的定时任务是如何实现的?有何注意点?
    在VMware Workstation Pro安装win7
    PEI是聚醚酰亚胺(Polyetherimide)在粘接使用时使用UV胶水的优势有哪些?要注意哪些事项?
    Flink学习13:Flink外接kafka数据源
    golang 函数式编程库samber/mo使用: Future
  • 原文地址:https://blog.csdn.net/taotiezhengfeng/article/details/126453671