一、spring启动时实现初始化的几种方式

准确的说是spring容器实例化完成后,几种初始化的方式。为什么这么说呢?下看面示例:

@slf4j
@component
public class initbeandemo {
    @autowired
    private environment env;

    public initbeandemo() {
        log.info("defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }

示例是在bean的构造方法里做一些初始化的工作,示例比较简单只做了日志打印。是理想很丰满,现实很骨感,报错了:constructor threw exception; nested exception is java.lang.nullpointerexception。
原因是,environment尚未初始化完成。

接下来我们来探索一下 有哪些初始化方式能满足上面示例的需求。

二、构造方法里初始化

可以正常运行,在所有初始化方式里执行时机最早。原理是在initbeandemo实例化前就实例化了environment。

@component
public class initbeandemo {

    private final environment env;

    @autowired
    public initbeandemo (environment environment) {
        this.env = environment;
        log.info("constructor defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("constructor activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }
}

三、常规三件套

常规三件套:@postconstruct、initializingbean、initmethod。 如果你愿意的话,三种方式可以在同一个bean下同时使用,执行的优先级@postconstruct > initializingbean > initmethod。

@postconstruct注解

在一个可以被扫描到bean里,添加一个public void xxx()方法并加上@postconstruct注解,方法里编写需要初始化的逻辑。
同一个应用程序里可以有多个@postconstruct注解,同一个bean里也可以有多个@postconstruct注解。

@slf4j
@component
public class initbeandemo {
    @autowired
    private environment env;

    @postconstruct
    public void init() {
        log.info("@postconstruct defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("@postconstruct activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }

实现initializingbean接口

实现initializingbean接口,在afterpropertiesset() 方法里编写需要初始化的逻辑。
同一个应用程序里可以有多个实现initializingbean接口的类,执行时机会按类名的自然顺序排序。

@slf4j
@component
public class initbeandemo implements initializingbean {
    @autowired
    private environment env;

    @override
    public void afterpropertiesset() throws exception {
        log.info("initializingbean defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("initializingbean activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }
}

指定bean的initmethod方法

使用@bean注解的initmethod属性可用于bean的初始化后执行的方法。initmethod必须是public void 的无参构造方法。

@slf4j
public class initbeandemo implements initializingbean {
    @autowired
    private environment env;
    
	public void initmethod() {
        log.info("initmethod defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("initmethod activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }
@configuration
public class initbeanconfig {

    @bean(initmethod="initmethod")
    public initbeandemo initbeandemo () {
        return new initbeandemo();
    }

}

等同于 在xml 配置中的init-method属性:

<bean id="initbeandemo" class="com.xxx.initbeandemo" init-method="initmethod"></bean>

四、自定义applicationlistener监听

两种方式,一种实现接口,另一种使用注解。

实现applicationlistener接口

监听contextrefreshedevent事件。

@slf4j
@component
public class initbeandemo implements applicationlistener<contextrefreshedevent>{
    @autowired
    private environment env;

    @override
    public void onapplicationevent(contextrefreshedevent event) {
        log.info("applicationlistener defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("applicationlistener activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }
}

@eventlistener注释

方法参数里指定contextrefreshedevent事件。

@slf4j
@component
public class initbeandemo {
    @autowired
    private environment env;

    @eventlistener
    public void onapplicationevent2(contextrefreshedevent event) {
        log.info("@eventlistener defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("@eventlistener activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }
}

五、spring boot提供的初始化接口

 applicationrunner接口

@slf4j
@component
public class initbeandemo implements applicationrunner {
    @autowired
    private environment env;

    @override
    public void run(applicationarguments args) throws exception {
        log.info("applicationrunner: {}", args);
        log.info("applicationrunner: {}", args.getoptionnames());
        log.info("applicationrunner defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("applicationrunner activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }
}

commandlinerunner接口

可以在同一个应用程序上下文中定义多个commandlinerunner bean,并且可以使用@ordered接口或@order注释进行排序。

@slf4j
@component
public class initbeandemo implements commandlinerunner {
    @autowired
    private environment env;

    @override
    public void run(string... args) throws exception {
        log.info("commandlinerunner: {}", args);
        log.info("commandlinerunner defaultprofiles: {}", arrays.aslist(env.getdefaultprofiles()));
        log.info("commandlinerunner activeprofiles: {}", arrays.aslist(env.getactiveprofiles()));
    }
}

在同一个bean里使用以上初始化方式的执行先后顺序

在同一个bean里使用以上初始化方式,运行的日志片段:

2021-06-07 11:24:41|info |main|c.c.s.s.t.constructorinitdemo|constructor defaultprofiles: [default]
2021-06-07 11:24:41|info |main|c.c.s.s.t.constructorinitdemo|constructor activeprofiles: [sit]
2021-06-07 11:24:42|info |main|c.c.s.s.test.initbeandemo|@postconstruct defaultprofiles: [default]
2021-06-07 11:24:42|info |main|c.c.s.s.test.initbeandemo|@postconstruct activeprofiles: [sit]
2021-06-07 11:24:42|info |main|c.c.s.s.test.initbeandemo|initializingbean defaultprofiles: [default]
2021-06-07 11:24:42|info |main|c.c.s.s.test.initbeandemo|initializingbean activeprofiles: [sit]
2021-06-07 11:24:42|info |main|c.c.s.s.test.initbeandemo|initmethod defaultprofiles: [default]
2021-06-07 11:24:42|info |main|c.c.s.s.test.initbeandemo|initmethod activeprofiles: [sit]
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|@eventlistener defaultprofiles: [default]
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|@eventlistener activeprofiles: [sit]
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|applicationlistener defaultprofiles: [default]
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|applicationlistener activeprofiles: [sit]
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|applicationrunner: org.springframework.boot.defaultapplicationarguments@68bef3df
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|applicationrunner: []
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|applicationrunner defaultprofiles: [default]
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|applicationrunner activeprofiles: [sit]
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|commandlinerunner: {}
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|commandlinerunner defaultprofiles: [default]
2021-06-07 11:24:44|info |main|c.c.s.s.test.initbeandemo|commandlinerunner activeprofiles: [sit]

也即 整篇文章整理的先后顺序。

到此这篇关于spring启动时实现初始化有哪些方式?的文章就介绍到这了,更多相关spring初始化内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!