zoukankan      html  css  js  c++  java
  • SpringBoot之启动加载器

    一、什么是启动加载器?

    在项目启动的时候做一些初始化工作。

    二、启动类加载器实践

    2.1 实现 CommandLineRunner 接口

    @Component
    public class FirstCommandLineRunner implements CommandLineRunner {
        @Override
        public void run(String... args) throws Exception {
            System.out.println("run FirstCommandLineRunner");
        }
    }
    

    2.2 实现 ApplicationRunner 接口

    @Component
    public class FirstApplicationRunner implements ApplicationRunner {
        @Override
        public void run(ApplicationArguments args) throws Exception {
            System.out.println("run FirstApplicationRunner");
        }
    }
    

    启动项目,观察控制台输出:

    run FirstApplicationRunner
    run FirstCommandLineRunner
    

    可以看到默认实现 ApplicationRunner 接口比 CommandLineRunner 优先级高。

    2.3 使用 @Order 注解

    我们试试看增加 @Order 注解之后会怎么样

    @Component
    @Order(1)
    public class FirstCommandLineRunner implements CommandLineRunner {
    	......
    }    
    @Component
    @Order(2)
    public class FirstApplicationRunner implements ApplicationRunner {
        ......
    }    
    

    启动项目,观察控制台输出:

    run FirstCommandLineRunner
    run FirstApplicationRunner
    

    发现 @Order 注解可以改变执行顺序。

    三、启动类加载器原理

    进入 SpringApplication.run 方法中,callRunners 方法就是入口:

    public ConfigurableApplicationContext run(String... args) {
    	......
    	callRunners(context, applicationArguments);
    	......
    }
    

    查看 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);
        // 循环调用 callRunner 方法
    	for (Object runner : new LinkedHashSet<>(runners)) {
    		if (runner instanceof ApplicationRunner) {
    			callRunner((ApplicationRunner) runner, args);
    		}
    		if (runner instanceof CommandLineRunner) {
    			callRunner((CommandLineRunner) runner, args);
    		}
    	}
    }
    

    可以看到先添加的 ApplicationRunner 接口实现,然后添加 CommandLineRunner 接口实现,所以默认优先级以 ApplicationRunner 为先,后面有个排序实现,以 @Order 进行优先级排序

    我们再来分别看下两个接口各自的 callRunner 的实现:

    private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
    	try {
    		(runner).run(args);
    	}
    	catch (Exception ex) {
    		throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
    	}
    }
    
    private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
    	try {
    		(runner).run(args.getSourceArgs());
    	}
    	catch (Exception ex) {
    		throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
    	}
    }	
    
  • 相关阅读:
    Learning to Compare: Relation Network for Few-Shot Learning 论文笔记
    修改python import模块中的变量
    roslaunch保存的log文件没有打印的ERROR信息
    python json demo
    vscode 1.32.x按下鼠标左键无法拖曳选择,而旧一点的版本1.30.2可以
    java-ee--------jdbc
    集合
    关键字
    java面向对象
    数组
  • 原文地址:https://www.cnblogs.com/markLogZhu/p/12510829.html
Copyright © 2011-2022 走看看