SpringBoot-流程注入操作

版权声明:来一来,看一看,有钱的捧个人场,没钱的你不得捧个人场 https://blog.csdn.net/wait_for_eva/article/details/82948765

IDEA快捷键

  • Ctrl+h: 查看接口实现类
  • Ctrl+Alt+<-:上一步
  • Ctrl+Alt+->:下一步

需要了解细节自己追吧,版本差异不大,主体流程还是一致。

注入接口

  • SpringApplicationRunListener
  • ApplicationContextInitializer
  • ApplicationRunner
  • CommandLineRunner
  • 这些方法注入比较安全,不会对SpringBoot本身有太大负担----别把入参玩坏了就行
  • 如果要定制环境什么的,高深一点就不行,只是插入流程而已
  1. 相同点

四种都是接口

  1. 差异点

后三种都只有一个方法,但是SpringApplicationRunListener流程监听器,生命周期决定了方法较多

接口结构

SpringApplicationRunListener

public interface SpringApplicationRunListener {
	void starting();
	void environmentPrepared(ConfigurableEnvironment environment);
	void contextPrepared(ConfigurableApplicationContext context);
	void contextLoaded(ConfigurableApplicationContext context);
	void started(ConfigurableApplicationContext context);
	void running(ConfigurableApplicationContext context);
	void failed(ConfigurableApplicationContext context, Throwable exception);
}
  • starting:开启
  • environmentPrepared:环境准备完毕
  • contextPrepared:上下文准备
  • contextLoaded:上下文加载完毕
  • started:应用正式启动
  • running:应用运行中
  • failed:失败

SpringApplicationRunListener方法贯穿SpringApplication,不用翻阅源码,也能大致了解

ApplicationContextInitializer

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
	void initialize(C applicationContext);
}

initialize:就一个方法

ApplicationRunner

public interface ApplicationRunner {
	void run(ApplicationArguments args) throws Exception;
}

run:没啥说的,结构不是重点

CommandLineRunner

public interface CommandLineRunner {
	void run(String... args) throws Exception;
}

run:参数不一样而已

接口顺序

  • 主体依照SpringApplicationRunListener顺序
  • environmentPrepared>ApplicationContextInitializer> contextPrepared
  • started>ApplicationRunner>CommandLineRunner>running

生效办法

  • classpath:META-INF/spring.factories
    在这里插入图片描述
org.springframework.boot.SpringApplicationRunListener=\
  com.godme.order.listener.MyRunListener
org.springframework.context.ApplicationContextInitializer=\
  com.godme.order.initializer.MyInitializer
  • @Component
@Component
public class MyApplicationRunner implements ApplicationRunner

@Component
public class MyCommandRunner implements CommandLineRunner 
  • SpringApplicationRunListenerApplicationContextInitializer必须写配置,没有则手动创建
  • ApplicationRunnerCommandLineRunner@Component注入容器就自动加载了

验证测试

  • 日志清理
# 笨办法,直接写文件,屏蔽控制台输出
logging.config=classpath:logback-godme.xml
<configuration>
    <appender name="syslog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>sys.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>ys.%d.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy  class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>1KB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>
                %d %p (%file:%line\)- %m%n
            </pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <logger name="com.godme.order.OrderApplication" level="DEBUG">
        <appender-ref ref="syslog" />
    </logger>
</configuration>


随便写点,不再干扰控制台输出就行。

  • Banner关闭
@SpringBootApplication
public class OrderApplication {
	public static void main(String[] args) {
		SpringApplication app = new SpringApplication(OrderApplication.class);
		app.setBannerMode(Banner.Mode.OFF);
		app.run(args);
	}
}

追源码就能清楚这个逻辑,关键在于BannerMode

  • 打印办法
public class Printer {
    private Printer(){}
    public static void print(){
        StackTraceElement trace = new Throwable().getStackTrace()[1];
        String className = trace.getClassName();
        String methodName = trace.getMethodName();
        String msg = className + getSpace(50 - className.length()) + methodName;
        System.err.println(msg);
    }
    public static String getSpace(int count){
        String spaces = "";
        while(count>0){
            spaces += " ";
            count--;
        }
        return spaces;
    }
}
  • 静态打印工具类, 格式为 className + spaces + methodName,有疑问的话参看静态方法获取调用类
  • 分列两行,格式化方便查看
  • System.err.printlnerr标红,显眼

然后把Printer.print方法填充进入全部实现接口类的方法中

  1. 阻塞

当遇见可能不会的情况,Ctrl+h,通过查看接口已实现类,或许能够获得灵感

  1. SpringApplicationRunListener构造
   public MyRunListener(SpringApplication application, String[] args) {
        Printer.print();
     }

需要有参构造,这就是Ctrl+h扒出来的

  • 运行结果
com.godme.order.listener.MyRunListener            <init>
com.godme.order.listener.MyRunListener            starting
com.godme.order.listener.MyRunListener            environmentPrepared
com.godme.order.initializer.MyInitializer         initialize
com.godme.order.listener.MyRunListener            contextPrepared
com.godme.order.listener.MyRunListener            contextLoaded
com.godme.order.listener.MyRunListener            started
com.godme.order.runner.MyApplicationRunner        run
com.godme.order.runner.MyCommandRunner            run
com.godme.order.listener.MyRunListener            running

可以看到,和追查逻辑一致

可能作用

SpringApplicationRunListener

public interface SpringApplicationRunListener {
	void starting();
	void environmentPrepared(ConfigurableEnvironment environment);
	void contextPrepared(ConfigurableApplicationContext context);
	void contextLoaded(ConfigurableApplicationContext context);
	void started(ConfigurableApplicationContext context);
	void running(ConfigurableApplicationContext context);
	void failed(ConfigurableApplicationContext context, Throwable exception);
}

除了environment之外,基本都是context,exception需要尽量避免的,精确处理也没太大必要性

个人觉得更多的是流程上的操作吧,关键在于context的利用程度加上操作时机

ApplicationContextInitializer

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
	void initialize(C applicationContext);
}

这个,除了时机错开之外,只能探究ApplicationContextInitializer周边关联了

要不一个ConfigurableApplicationContext玩啥啊,自定义一个也会有新玩法

ApplicationRunner

public interface ApplicationRunner {
	void run(ApplicationArguments args) throws Exception;
}

除了时机的话,这个会有参数,或许可以制定些参数操作

CommandLineRunner

public interface CommandLineRunner {
	void run(String... args) throws Exception;
}

同上

杂烩

​ 同时实现多个接口,同时添加关联参数的话,也是一个新天地。

猜你喜欢

转载自blog.csdn.net/wait_for_eva/article/details/82948765