乐趣区

关于java:Spring-Boot之-CommandLineRunnerApplicationRunner和PostConstruct

 在应用 Spring Boot 开发的工作中,咱们常常会须要遇到一种性能需要,比方在服务启动时候,去加载一些配置,去申请一下其余服务的接口。Spring Boot 给咱们提供了三种罕用的实现办法:第一种是实现 CommandLineRunner 接口,第二种是实现 ApplicationRunner 接口
第三种是应用注解:@PostConstruct

1、CommandLineRunner

1、CommandLineRunner 执行的工夫节点是在 Application 实现初始化工作之后。2、CommandLineRunner 在有多个实现的时候,能够应用 @order 注解指定执行先后顺序。3、源码在:org.springframework.boot.SpringApplication#run(),能够看看 

咱们先看一下 CommandLineRunner 的源码:

package org.springframework.boot;

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

SpringApplication 源码:

public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {this.handleRunFailure(context, var10, listeners);
            throw new IllegalStateException(var10);
        }

        try {listeners.running(context);
            return context;
        } catch (Throwable var9) {this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

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);
            }
        }

    }

咱们写一个例子实现:

 
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Order(1)
public class CommandLineRunnerTest implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {System.out.println("----CommandLineRunnerTest1 start---"+ Arrays.toString(args));
    }
}

2、ApplicationRunner

ApplicationRunner 跟 CommandLineRunner 是区别是在 run 办法里接管的参数不同,CommandLineRuner 接管的参数是 String... args,而 ApplicationRunner 的 run 办法的参数是 ApplicationArguments 

看看 ApplicationRunner 的源码:

package org.springframework.boot;

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

咱们写一个例子实现:


import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;

@Component
@Order(1)
public class ApplicationRunnerTest implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {System.out.println("---ApplicationRunnerTest start----");

        List<String> nonOptionArgs = args.getNonOptionArgs();
        System.out.println("[ 非选项参数]>>>" + nonOptionArgs);
        Set<String> optionNames = args.getOptionNames();
        for(String optionName: optionNames) {System.out.println("[ 选项参数]>>> name:" + optionName
                    + ";value:" + args.getOptionValues(optionName));
        }
    }
}

3、@PostConstruct

@PostConstruct 是在 javaEE5 的时候引入的, 它并不是 Spring 提供的,然而 Spring 有对 @PostConstruct 的实现。并且是在对象加载完之后执行。

先看注解源码

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

咱们写一个例子实现:

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class PostConstructTest {

    @PostConstruct
    public void start(){System.out.println("---PostConstruct start---");
    }


}

运行代码输入后果:

5、源码

https://gitee.com/Qinux/comma…

 微信公众号:一凡码农
欢送交换 
退出移动版