在springboot项目中创建组件类实现commandlinerunner或applicationrunner接口可实现在应用启动之后及时进行一些初始化操作,如缓存预热、索引重建等等类似一些数据初始化操作。
两个接口功能相同,都有个run方法需要重写,只是实现方法的参数不同。
commandlinerunner接收原始的命令行启动参数,app寻找前世之旅第二季licationrunner则将启动参数对象化。
两个接口都是在springboot应用初始化好上下文之后运行,所以在运行过程中,可以使用上下文中的所有信息,例如一些bean等等。在框架springapplication类源码的run方法中,可查看runner的调用时机callrunners,如下:
/** * run the spring application, creating and refreshing a 产品设计作品new * {@link applicationcontext}. * @param args the application arguments (usually pasd from a java main method) * @return a running {@link applicationcontext} */public configurableapplicationcontext run(string... args) {stopwatch stopwatch = new stopwatch();stopwatch.start();configurableapplicationcontext context = null;collection<springbootexceptionreporter> exceptionreporters = new arraylist<>();configureheadlessproperty();springapplicationrunlisteners listeners = getrunlisteners(args);listeners.starting();try {applicationarguments applicationarguments = new defaultapplicationarguments(args);configurableenvironment environment = prepareenvironment(listeners, applicationarguments);configureignorebeaninfo(environment);banner printedbanner = printbanner(environment);context = createapplicationcontext();exceptionreporters = getspringfactoriesinstances(springbootexceptionreporter.class,new class[] { configurableapplicationcontext.class }, context);preparecontext(context, environment, listeners, applicationarguments, printedbanner);refreshcontext(context);afterrefresh(context, applicationarguments);stopwatch.stop();if (this.logstartupinfo) {new startupinfologger(this.mainapplicationclass).logstarted(getapplicationlog(), stopwatch);}listeners.started(context);//调用runner,执行初始化操作callrunners(context, applicationarguments);}catch (throwable ex) {handlerunfailure(context, ex, exceptionreporters, listeners);throw new illegalstateexception(ex);}try {listeners.running(context);}catch (throwable ex) {handlerunfailure(context, ex, exceptionreporters, null);throw new illegalstateexception(ex);}return context;}
2.1 commandlinerunner
简单实现如下,打印启动参数信息:
@order(1)@componentpublic class commandlinerunnerinit implements commandlinerunner { private logger logger = loggerfactory.getlogger(this.getclass()); private final string log_prefix = ">>>>>>>>>>commandlinerunner >>>>>>>>>> "; @override public void run(string... args) throws exception { try { this.logger.error("{}园林专业排名 args:{}", log_prefix, stringutils.join(args, ",")); } catch (exception e) { logger.error("commandlinerunnerinit run failed", e); } }}
2.2 applicationrunner
简单实现如下,打印启动参数信息,并调用bean的方法(查询用户数量):
@order(2)@componentpublic class applicationrunnerinit implements applicationrunner { private logger logger = loggerfactory.getlogger(this.getclass()); private final string log_prefix = ">>>>>>>>>>applicationrunner >>>>>>>>>> "; private final urrepository urrepository; public applicationrunnerinit(urrepository urrepository) { this.urrepository = urrepository; } @override public void run(applicationarguments args) throws exception { try { this.logger.error("{} args:{}", log_prefix, jsonobject.tojsonstring(args)); for (string optionname : args.getoptionnames()) { this.logger.error("{} argname:{} argvalue:{}", log_prefix, optionname, args.getoptionvalues(optionname)); } this.logger.error("{} ur count:{}", log_prefix, this.urrepository.count()); } catch (exception e) { logger.error("commandlinerunnerinit run failed", e); } }}
如果实现了多个runner,默认会按照添加顺序先执行applicationrunner的实现再执行commandlinerunner的实现,如果多个runner之间的初始化逻辑有先后顺序,可在实现类添加@order注解设置执行顺序,可在源码springapplication类的callrunners方法中查看,如下:
private void callrunners(applicationcontext context, applicationarguments args) { list<object> runners = new arraylist<>(); //先添加的applicationrunner实现 runners.addall(context.getbeansoftype(applicationrunner.class).values()); //再添加的commandlinerunner实现 runners.addall(context.getbeansoftype(commandlinerunner.class).values()); //如果设置了顺序,则按设定顺序重新排序 annotationawareordercomparator.sort(runners); for (object runner : new linkedhasht<>(runners)) { if (runner instanceof applicationrunner) { callrunner((applicationrunner) runner, args); } if (runner instanceof commandlinerunner) { callrunner((commandlinerunner) runner, args); } }}
为了便于对比效果,在idea中设置启动参数如下图(生产环境中会自动读取命令行启动参数):
在上面的两个runner中,设定了commandlinerunnerinit是第一个,applicationrunnerinit是第二个。启动应用,运行效果如下图:
业务场景:
应用服务启动时,加载一些数据和执行一些应用的初始化动作。如:删除临时文件,清除缓存信息,读取配置文件信息,数据库连接等。
1、springboot提供了commandlinerunner和applicationrunner接口。当接口有多个实现类时,提供了@order注解实现自定义执行顺序,也可以实现ordered接口来自定义顺序。
注意:数字越小,优先级越高,也就是@order(1)注解的类会在@order(2)注解的类之前执行。
两者的区别在于:
applicationrunner中run方法的参数为applicationarguments,而commandlinerunner接口中run方法的参数为string数组。想要更详细地获取命令行参数,那就使用applicationrunner接口
@component@order(value = 10)public class agentapplicationrun2 implements applicationrunner { @override public void run(applicationarguments applicationarguments) throws exception { }}
@口琴演奏component@order(value = 11)public class agentapplicationrun implements commandlinerunner { @override public void run(string... strings) throws exception { }}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。
本文发布于:2023-04-04 04:31:46,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/181aa2d7603ab3ac8763b33582c2b69b.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:应用启动数据初始化接口CommandLineRunner和Application详解.doc
本文 PDF 下载地址:应用启动数据初始化接口CommandLineRunner和Application详解.pdf
留言与评论(共有 0 条评论) |