Springboot中随时获取ApplicationContext,得到想要的bean

本文介绍了一个SpringBoot项目的启动过程,并实现了一个工具类用于在启动时加载Spring上下文及初始化特定的服务。此外,还实现了自动开启符合条件的预警任务的功能。

在springBoot启动类的main方法中写成

/**
     * 启动嵌入式的Tomcat并初始化Spring环境
     */
    public static void main(String[] args) throws Exception {
        ApplicationContext app = SpringApplication.run(WebApplication.class, args);
        SpringUtil.setApplicationContext(app);
        //SpringApplication.run(WebApplication.class, args);
    }

创建工具类

package com.yssoft.fs.supervise.utils;

import com.yssoft.fs.repository.entity.comm.EarlyWarningTask;
import com.yssoft.fs.supervise.service.riskWarning.RiskWarningTaskService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;

import javax.annotation.Resource;
import java.util.List;

public class SpringUtil  {

    private static ApplicationContext applicationContext = null;
// 非@import显式注入,@Component是必须的,且该类必须与main同包或子包
    // 若非同包或子包,则需手动import 注入,有没有@Component都一样
    // 可复制到Test同包测试

    public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(SpringUtil.applicationContext == null){
            SpringUtil.applicationContext  = applicationContext;
        }
        //查询所有预警任务,开启的预警任务自动开启
        RiskWarningTaskService riskWarningTaskServiceStatic=applicationContext.getBean(RiskWarningTaskService.class);
        List<EarlyWarningTask> earlyWarningTask = riskWarningTaskServiceStatic.findEarlyWarningTaskAll();
        for (EarlyWarningTask warningTask : earlyWarningTask) {
            //如果任务是打开的,可就开启任务
            if("1".equals(warningTask.getStat())){
                riskWarningTaskServiceStatic.editState("1",warningTask.getId().toString(),warningTask.getTitle());
                riskWarningTaskServiceStatic.editState("0",warningTask.getId().toString(),warningTask.getTitle());
            }
        }
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);

    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }

}
<think> 嗯,用户询问的是在Spring Boot启动类中获取ApplicationContext方法。这个问题比较明确,但需要结合Spring Boot的启动机制来回答。从引用内容看,有几处关键信息值得注意: 引用[1]提到工具类注入ApplicationContext的两种启动方式差异,这暗示获取方式可能受启动类型影响;引用[2]详细展示了SpringApplication.run()方法内部创建context的过程,特别是refreshContext(context)这个关键节点;引用[3]强调了ApplicationContext作为IoC容器的核心地位;引用[5]则说明启动类本身也是被管理的Bean。 用户可能正在开发需要全局访问容器的功能,比如工具类中动态获取Bean。考虑到Spring Boot的启动流程,最直接的方式应该是利用启动类的main方法返回值——因为run()方法返回的就是ConfigurableApplicationContext实例。这点在引用[2]的代码片段中体现得很清楚。 不过要注意线程安全问题。虽然启动类中获取context很简单,但如果在其他线程使用这个context需要谨慎。另外引用[1]提到的war包启动场景,理论上获取方式应该相同,但可能需要验证外置tomcat是否会影响context生命周期。 用户没有提到具体使用场景,所以补充了两种替代方案:实现ApplicationContextAware接口适用于常规Bean,而监听事件的方式更优雅但稍复杂。这些方案在引用[3]和[5]中都有理论基础支持。 最后生成的问题覆盖了进阶用法:生命周期时机很重要,因为启动初期有些Bean还未初始化;自动装配的关系则是理解原理的关键;性能影响则是生产环境必须考虑的。 </think> 以下是Spring Boot启动类中获取`ApplicationContext`的三种核心方法,结合启动流程详解: --- ### 方法1:通过`SpringApplication.run()`返回值直接获取(推荐) 在`main()`方法中捕获`run()`方法返回的`ApplicationContext`: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @SpringBootApplication public class MyApp { public static void main(String[] args) { // 直接获取ApplicationContext实例 [^2][^5] ApplicationContext context = SpringApplication.run(MyApp.class, args); // 使用示例:获取Bean MyService service = context.getBean(MyService.class); service.execute(); } } ``` **原理**: `SpringApplication.run()`方法内部会创建并刷新`ApplicationContext`(见`refreshContext(context)`[^2]),最终返回初始化完成的上下文实例。 --- ### 方法2:实现`ApplicationContextAware`接口 适用于非静态场景(如需要注入到组件中): ```java import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @Component public class ContextHolder implements ApplicationContextAware { private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext ctx) { context = ctx; // Spring自动注入上下文 [^3] } public static ApplicationContext getContext() { return context; } } ``` **启动类调用**: ```java @SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); MyBean bean = ContextHolder.getContext().getBean(MyBean.class); // 通过工具类获取 } } ``` --- ### 方法3:监听`ApplicationReadyEvent`事件 在容器完全初始化后安全获取上下文: ```java import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationContext; import org.springframework.boot.context.event.ApplicationReadyEvent; @SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication app = new SpringApplication(MyApp.class); app.addListeners((ApplicationListener<ApplicationReadyEvent>) event -> { ApplicationContext context = event.getApplicationContext(); // 事件触发时获取 [^5] // 执行容器就绪后的操作 }); app.run(args); } } ``` --- ### 关键流程说明 1. **上下文创建**: `SpringApplication.run()` → `createApplicationContext()` → 创建`AnnotationConfigApplicationContext`(Web应用为`AnnotationConfigServletWebServerApplicationContext`)[^2][^5]。 2. **上下文初始化**: 通过`refreshContext()`触发Bean加载、依赖注入等核心流程(包含`@ComponentScan`扫描)[^4][^5]。 3. **注入时机**: `ApplicationContextAware`的注入发生在Bean初始化阶段,早于`ApplicationReadyEvent`事件[^3][^5]。 > ⚠️ **注意**:若在Bean初始化阶段(如`@PostConstruct`方法中)使用上下文,优先选择`ApplicationContextAware`;静态工具类场景推荐方法1或2。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值