SpringBoot启动自动执行

SpringBoot启动自动执行的几种方式

一、实现ApplicationRunner接口

​ 实现ApplicationRunner接口的run方法,其中重写方法的参数是启动命令中的Program arguments参数,该实现是在Spring容器启动之后通过调用callRunners()方法执行,会从Spring容器中获取所有的ApplicationRunner实现类与CommandLineRunner实现类,并且排序后执行,也就是执行该方法的时候可以获取Spring容器中的bean,也可以实现多个,通过注解@Order或者实现以下接口之一(Ordered,PriorityOrdered)自定义顺序。该方法的执行和CommandLineRunner实现类的方法执行在一个线程中,因此最好不要出现死循环。

@Component
public class MyApplicationRunner implements ApplicationRunner {
    private static Logger logger = LoggerFactory.getLogger(MyApplicationRunner.class);
    @Override
    public void run(ApplicationArguments args) throws Exception {
        logger.info("开始执行ApplicationRunner接口实现类的run方法");
        for (String sourceArg : args.getSourceArgs()) {
            logger.info("sourceArge:{}",sourceArg);
        }
        Set<String> optionNames = args.getOptionNames();
        optionNames.forEach(x->{
            logger.info("option:{}",x);
        });
    }
}

​ callRunners()方法源码如下:

private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList();
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    AnnotationAwareOrderComparator.sort(runners);
    Iterator var4 = (new LinkedHashSet(runners)).iterator();
    while(var4.hasNext()) {
        Object runner = var4.next();
        if (runner instanceof ApplicationRunner) {
            this.callRunner((ApplicationRunner)runner, args);
        }

        if (runner instanceof CommandLineRunner) {
            this.callRunner((CommandLineRunner)runner, args);
        }
    }
}

二、实现CommandLineRunner接口

​ 实现CommandLineRunner接口的run方法传入的参数是"key=value"的字符串,也是Program arguments参数,也可以通过注解@Order进行排序。通过上面callRunner方法的源码可以看出来.

@Component
public class MyCommondLineRunner implements CommandLineRunner {
    private static Logger logger = LoggerFactory.getLogger(MyCommondLineRunner.class);
    @Override
    public void run(String... args) throws Exception {
        logger.info("实现了CommandLineRunner的run方法");
        for (String arg : args) {
            logger.info("arg:{}",arg);
        }
    }
}

三、实现ServletContextAware接口

​ 实现ServletContextAware接口的setServletContext方法,它是Spring中就已经存在的接口。

@Component
public class MyServletContextAware implements ServletContextAware {
    private static Logger logger = LoggerFactory.getLogger(MyServletContextAware.class);
    @Override
    public void setServletContext(ServletContext servletContext) {
        logger.info("实现了MyServletContextAware的setServletContext方法");
    }
}

​ 具体在使用中,在加载Bean之前(初始化Bean的准备准备工作时)就会将servletContext放入该对象中,但是通过执行测试执行该方法时bean已经初始化,故可以使用依赖注入。bean在执行实例方法调用的时候才会被加载。

四、实现ServletContextListener接口

​ 实现ServletContextListener的contextInitialized方法,在ServletContextListener实现类之前执行,ServletContext初始化之后执行,用于ServletContext对象的生命周期监听,可以是实现contextDestroyed()方法用于ServletContext对象释放后执行。也可以进行依赖注入。

@Component
public class MyServletContextListener implements ServletContextListener {
    private static Logger logger = LoggerFactory.getLogger(MyServletContextListener.class);

    @Override
    public void contextInitialized(ServletContextEvent sce) {

        ServletContext servletContext = sce.getServletContext();
        logger.info("实现了ServletContextListeneri接口的contextInitialized方法");
    }
}

五、实现ApplicationListener接口

​ 实现ApplicationListener接口的onApplicationEvent方法,

@Component
public class MyApplicationLisenter implements ApplicationListener<ContextRefreshedEvent> {

    private static Logger logger = LoggerFactory.getLogger(MyApplicationLisenter.class);

    @Override
    public void onApplicationEvent(ContextRefreshedEvent e) {
        logger.info("实现了ApplicationListener的onApplicationEvent方法");
    }
}

Spring内部有一下监听事件,如果需要自定义事件需要实现ApplicationEvent抽象类。

类名描述
ContextRefreshedEventApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用
ContextStartedEvent当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
ContextStoppedEvent当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
ContextClosedEvent当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
RequestHandledEvent这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。

自定义方法触发时间如下:

public class SpringTest {
   public static void main(String args[]){
     ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
     //创建一个ApplicationEvent对象
     EmailEvent event = new EmailEvent("hello","abc@163.com","This is a test");
     //主动触发该事件
     context.publishEvent(event);
   }
}

六、注解@PostConstruct与Spring容器中的static方法

​ 添加了注解@PostConstruct的方法会在启动时被执行,Bean在被初始化之后就会执行带有@PostConstruct的方法,该方法只会被服务器执行一次,该注解执行用在返回值为void且没有传参的方法,这是JSR-250的规范,Spring容器中的static方法也会在加载该类的时候执行。

@Component
public class MyPostConstruct {
    private static Logger logger = LoggerFactory.getLogger(MyPostConstruct.class);
    static {
        logger.info("MyPostConstruct静态代码块");
    }
    @PostConstruct
    public void hhhh() {
        logger.info("注解@PostConstruct所在的方法");
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值