详细SpringBoot生命周期接口的使用(springboot接口的开发流程)

网友投稿 374 2022-07-28


目录一 背景二 SpringBoot 生命周期接口三 后记

一 背景

最近在做一个项目启动时加载配置到SpringBoot容器中的功能,看到了Spring中有很多在容器初始化时的接口,这些接口或注解包括InitializingBean、@PostConstruct、SmartInitializingSingleton、BeanPostProcess等等,这么多都可以在初始化时使用,但是他们有什么区别呢,下面就来说说他们之间的区别

二 SpringBoot 生命周期接口

@PostConstruct

这个注解在实际的开发中有较多的用到

@Component

public class TestP {

@PostConstruct

public void test() {

System.out.println("@PostConstruct");

}

这样在容器启动过程中就回执行打印,看起来他像是对象的构造方法,其实他的作用是,当一个对象A中存在@Autowire修饰的依赖B时,正常来说,对象会先执行自己的构造方法,然后再去注入依赖,但是我们现在有一种情况,在对象实例化时,要执行构造方法,但是构造方法中用到依赖B,这个时候用 @PostConstruct就能解决这个问题。

public class TestP implements InitializingBean, SmartInitializingSingleton {

@Autowired

Context context;

```

public TestP () {

System.out.prhttp://intln(context);

}

```

@PostConstruct

public void test() {

System.out.println(context);

System.out.println("@PostConstruct");

}

输出

null com.example.demo1.bean.Context@4f96a58 @PostConstruct

InitializingBean

他提供bean初始化的回调处理功能,看下这个接口的源码

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {

boolean isInitializingBean = (bean instanceof InitializingBean);

//判断该bean是否实现了实现了InitializingBean接口,如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法

if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {

if (logger.isDebugEnabled()) {

logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");

}

if (System.getSecurityManager() != null) {

try {

AccessController.doPrivileged(new PrivilegedExceptionAction() {

public Object run() throws Exception {

//直接调用afterPropertiesSet

((InitializingBean) bean).afterPropertiesSet();

return null;

}

},getAccessControlContext());

} catch (PrivilegedActionException pae) {

throw pae.getException();

}

}

else {

//直接调用afterPropertiesSet

((InitializingBean) bean).afterPropertiesSet();

}

}

if (mbd != null) {

String initMethodName = mbd.getInitMethodName();

//判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method

if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&

!mbd.isExternallyManagedInitMethod(initMethodName)) {

//进一步查看该方法的源码,可以发现init-method方法中指定的方法是通过反射实现

invokeCustomInitMethod(beanName, bean, mbd);

}

}

可以看到,只要实现了这个接口的bean都会执行里面的afterPropertiesSet方法,那他和 @PostConstruct有什么区别呢,区别是他们的生命周期排序不同,@PostConstruct是对单个Bean实例化时使用,而InitializingBean是在所有spring bean实例化后对bean进行处理,⼤致的步骤是这样的

实例化bean,这⾥会调⽤构造⽅法

填充属性,就是依赖注⼊

初始化bean,

调⽤后置处理器,其中会执⾏@PostConstruct注解⽅法执⾏bean的⽣命周期中的初始化回调⽅法,也就是InitializingBean接⼝的afterPropertiesSet()⽅法BeanPostProcess

这个接口主要是对注册的bean中的属性进行初始化时的修改

@Component

public class Beanhttp://PostTest implements BeanPostProcessor {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("执行1--------------- - " + bean.getClass().getName() + " - " + beanName);

return null;

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("执行2--------------- - " + bean.getClass().getName() + " - " + beanName);

return null;

}

}

他和InitializingBean区别一个是执行顺序不同

他有两个方法分别在在InitializingBean执行前执行后执行,第二个区别就是InitializingBean是一个可以进一步调整bean的实例的接口,不过并不是每个类都会来执行这个接口方法,这个接口只针对当前实现类,而BeanPostProcess是针对所有bean的,每一个bean被注册,都会被执行一次这两个方法

SmartInitializingSingleton

这个是在spring 4.1版本才推出的接口,他的执行时时机是在单例预实例化阶段结束时调用,并保证已经创建了所有常规单例bean,所以他的执行顺序是比较靠后的,考虑到一些bean的注册及修改使用SmartInitializingSingleton是比较稳妥的一种方式

```

@Component

public class GetuiAccountConfigInit implements SmartInitializingSingleton {

@Override

public void afterSingletonsInstantiated() {

}

}

```

Commandlinerunner 这个接口是springBoot的接口,他是在所有bean都加载后才会执行的,如果实现这个接口,可以很好的在启动时初始化资源,因为所有的bean都可以使用了

@Component

public class Runner implements CommandLineRunner {

@Override

public void run(String... args) throws Exception {

System.out.println("执行初始化");

}

}

如果我们要执行的程序有顺序要求,还可以使用@Order注解

@Component

@Order(1)

public class OrderRunner1 implements CommandLineRunner {

@Override

public void run(String... args) throws Exception {

System.out.println("The OrderRunner1 start to initialize ...");

}

}

@Component

@Order(2)

public class OrderRunner1 implements CommandLineRunner {

@Override

public void run(String... args) throws Exception {

System.out.println("The OrderRunner2 start to initialize ...");

}

}

三 后记

Spring由于设计上比较灵活所以留了很多接口,让开发人员进行拓展,这本身是一个很好的学习借鉴的经验,现在大部分的开发使用的都是spring的框架,这就要求我们做一些设计时要了解框架的特性,才能进行更好的设计,上面的几http://个接口是相对来说比较常用的接口,里面的技术细节也值得推敲,希望对大家有所帮助。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:基于Java实现双向链表(java实现单向链表的数据结构)
下一篇:springboot vue测试平台接口定义前后端新增功能实现
相关文章

 发表评论

暂时没有评论,来抢沙发吧~