SpringBoot基础篇(三)ApplicationContextAware和CommandLineRunner接口

本文深入探讨SpringBoot中两个核心接口:ApplicationContextAware和CommandLineRunner的使用。详细介绍了如何利用ApplicationContextAware获取Spring容器中的bean,以及如何通过实现CommandLineRunner在服务启动时执行特定任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.ApplicationContextAware接口

        ApplicationContext对象是Spring开源框架的上下文对象实例,在项目运行时自动装载Handler内的所有信息到内存。基于SpringBoot平台完成ApplicationContext对象的获取,并通过实例手动获取Spring管理的bean。

ApplicationContextAware接口的方式获取ApplicationContext对象实例,但并不是SpringBoot特有的功能,早在Spring3.0x版本之后就存在了这个接口,在传统的Spring项目内同样是可以获取到ApplicationContext实例的。

/**
 * Spring的ApplicationContext的持有者,可以用静态方法的方式获取spring容器中的bean
 *@Component不能去掉,否则无法调用setApplicationContext方法
 */
@Component
public class SpringContextHolder implements ApplicationContextAware {
	/**
	 * 上下文对象实例
	 */
	private static ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		SpringContextHolder.applicationContext = applicationContext;
	}
/**
 * 获取application上下文对象
 * @return
 */
	public static ApplicationContext getApplicationContext() {
		assertApplicationContext();
		return applicationContext;
	}

	/**
	 * 通过name获取bean
	 * @param beanName
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String beanName) {
		assertApplicationContext();
		return (T) applicationContext.getBean(beanName);
	}

	/**
	 * 通过class获取bean
	 * @param requiredType
	 * @return
	 */
	public static <T> T getBean(Class<T> requiredType) {
		assertApplicationContext();
		return applicationContext.getBean(requiredType);
	}

	private static void assertApplicationContext() {
		if (SpringContextHolder.applicationContext == null) {
			throw new RuntimeException("applicaitonContext属性为null,请检查是否注入了SpringContextHolder!");
		}
	}

}

 【上述代码注意实现】(1)ApplicationContextProvider类上的@Component注解是不可以去掉的,去掉后Spring就不会自动调用setApplicationContext方法来为我们设置上下文实例。

(2)我们把SpringContextHolder作为工具类,使用SpringContextHolder.getBean()方式直接调用获取。

2.CommandLineRunner接口

     在实际应用中,我们会在项目服务启动的时候就去加载一些数据或者做一些事情这样的需求。为了解决这个问题,springboot为我们提供了一个方法,通过实现接口CommandLineRunner来实现。

**
 * 服务器启动时执行
 */
@Component
public class MyStartRunning implements CommandLineRunner
{
    @Autowired
    private IDeptService deptService;
    @Override
    public void run(String... args) throws Exception
    {
        System.out.println("============服务器启动时执行================");
        for (String arg:args){
            //args参数数组是启动传入进来的
            System.out.println("========执行的参数====="+arg);
        }
        Dept dept = deptService.selectById(25);
        System.out.println("=======dept:======="+dept.toString());
    }
}

 

 

 

 

<think>我们有一个用户问题:如何让JavaCommandLineRunner执行完成后自动退出程序?根据引用内容,我们知道CommandLineRunnerSpringBoot应用启动后执行的一个回调接口。通常,SpringBoot应用启动后会一直运行(比如作为Web应用监听端口),但有时我们只想执行一些任务然后退出。解决方案思路:1.在CommandLineRunner的run方法中执行完任务后,主动调用退出方法。2.可以通过获取Spring上下文并关闭它,从而让整个应用退出。具体步骤:我们可以使用`ConfigurableApplicationContext`的`close()`方法来关闭应用上下文,进而使JVM退出。示例代码:在CommandLineRunner的实现中,我们可以注入`ApplicationContext`(注意是ConfigurableApplicationContext,因为它有close方法),然后在任务执行完毕后关闭上下文。注意:如果我们的应用是Web应用(例如有内嵌的Tomcat),关闭上下文也会停止Web服务器。代码示例:```javaimportorg.springframework.boot.CommandLineRunner;importorg.springframework.context.ConfigurableApplicationContext;importorg.springframework.stereotype.Component;@ComponentpublicclassTaskRunnerimplementsCommandLineRunner{privatefinalConfigurableApplicationContextcontext;//通过构造函数注入ConfigurableApplicationContextpublicTaskRunner(ConfigurableApplicationContextcontext){this.context=context;}@Overridepublicvoidrun(String...args)throwsException{//执行你的任务System.out.println("开始执行任务...");//模拟任务执行Thread.sleep(2000);System.out.println("任务执行完毕,准备退出程序。");//关闭Spring应用上下文,这将导致应用退出context.close();}}```另一种方法是使用`SpringApplication.exit(context,exitCode)`,它也会关闭应用上下文。示例:```javaintexitCode=SpringApplication.exit(context);System.exit(exitCode);```但通常直接调用`context.close()`即可。注意:如果应用启动时有多个CommandLineRunner,注意关闭上下文的操作应该在最后一个要执行的Runner中,或者根据业务逻辑决定何时关闭。另外,如果不想在代码中直接注入上下文,也可以使用`ApplicationContextAware`接口来获取上下文,但注入方式更简单。参考引用[2]中提到了DisposableBean接口,但这里我们不需要它,因为关闭上下文会自动触发销毁回调。因此,在CommandLineRunner中关闭Spring上下文即可实现任务完成后退出程序。相关问题:1.如何在SpringBoot中执行一次性任务并退出?2.CommandLineRunnerApplicationRunner的区别是什么?3.如何控制多个CommandLineRunner的执行顺序?</think>### 如何让 CommandLineRunner 执行后自动退出程序 在 Spring Boot 中让 `CommandLineRunner` 执行后自动退出程序的核心方法是**主动关闭应用上下文**。以下是实现步骤代码示例: #### 解决方案 1. **获取应用上下文** 通过 `ConfigurableApplicationContext` 接口获取可配置的上下文对象 2. **执行后主动关闭** 在 `CommandLineRunner.run()` 方法末尾调用 `context.close()` 关闭上下文 ```java import org.springframework.boot.CommandLineRunner; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.stereotype.Component; @Component public class AutoExitRunner implements CommandLineRunner { private final ConfigurableApplicationContext context; // 通过构造函数注入上下文 public AutoExitRunner(ConfigurableApplicationContext context) { this.context = context; } @Override public void run(String... args) throws Exception { System.out.println("开始执行任务..."); // 执行你的业务逻辑(示例) for (int i = 0; i < 5; i++) { System.out.println("处理任务-" + i); Thread.sleep(1000); } System.out.println("任务执行完成,退出程序"); // 关键步骤:主动关闭应用上下文 context.close(); } } ``` #### 实现原理 - `context.close()` 会触发 Spring Boot 的优雅关闭流程: 1. 发送 `ContextClosedEvent` 事件 2. 调用所有 `DisposableBean` 的 `destroy()` 方法[^2] 3. 停止内嵌 Web 容器(如果存在) 4. 退出 JVM 进程 #### 替代方案 ```java // 使用SpringApplication.exit()方法 int exitCode = SpringApplication.exit(context); System.exit(exitCode); ``` #### 注意事项 1. 确保没有其他阻塞线程(如 Web 服务) 2. 如需返回退出码: ```java // 在application.properties中配置 spring.main.web-application-type=none ``` 3. 多个 `CommandLineRunner` 时需控制关闭时机 > 示例中通过构造函数注入 `ConfigurableApplicationContext` 是推荐方式,也可实现 `ApplicationContextAware` 接口获取上下文[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值