五、LifecycleBean 和 @Init、@Destroy
LifecycleBean 接口,是绑定应用上下文(AppContext)的启动与停止的。
- 启动时,Bean 扫描已经结束,可以做一些初始化动作(@Init 函数,与此相当)
- 启动之后,一般开始网络监听与注册
- 停止之前,一般注销网络登记
- 停止时,可以做一些释放动作(@Destroy 函数,与此相当)
它,只对单例有效。非单例时,仅扫描时产生的第一实例会被纳管,其它实例的生命周期会失效(或者自己处理)。当有多个 LifecycleBean 相互依赖时,会自动排序。
接口 | 对应注解 | 执行时机 | 说明 |
---|---|---|---|
LifecycleBean::start | @Init | AppContext::start() | 启动 |
LifecycleBean::postStart | 同上 | 启动之后 | |
LifecycleBean::preStop | AppContext::preStop() | 停止之前 | |
LifecycleBean::stop | @Destroy | AppContext::stop() | 停止 |
1、使用 @Init
、@Destroy
替代轻量
如果不需要 LifecycleBean::stop
,使用注解 @Init
更简洁。一般只做初始化处理。
@Component
public class Demo {
@Init
public void init(){ //一个无参的函数,名字随便取
}
}
如果不需要 LifecycleBean::start
,使用注解 @Destroy
更简洁。一般只做注销处理。
@Component
public class Demo {
@Destroy
public void destroy(){ //一个无参的函数,名字随便取
}
}
2、LifecycleBean 的自动排序(v2.2.8 后支持)
自动排序。当 Bean2 依赖 Bean1 注入时。Bean1::start() 会先执行,再执行 Bean2::start()。例:
@Component
public class Bean1 implements LifecycleBean{
@Override
public void start(){
//db1 init ...
}
public void func1(){
//db1 call
}
}
@Component
public class Bean2 implements LifecycleBean{
@Inject
Bean1 bean1;
@Override
public void start(){
bean1.func1();
}
}
有时候 Bean1 和 Bean2 可能并没有直接的依赖关系。也是可以通过注入,形成依赖关系,让执行自动排序(这个可称为"小技巧")
3、LifecycleBean 自动排序引起的循环依赖问题
因为自动排序是基于注入的依赖关系来确定的。当相互依赖时就会傻掉(异常提示)。像这样:
@Component
public class Bean1 implements LifecycleBean{
@Inject
Bean2 bean2;
@Override
public void start(){
}
}
@Component
public class Bean2 implements LifecycleBean{
@Inject
Bean1 bean1;
@Override
public void start(){
}
}
要么取消相互依赖。要么手工指定顺序位:
@Component(index = 1)
public class Bean1 implements LifecycleBean{
@Inject
Bean2 bean2;
@Override
public void start(){
}
}
@Component(index = 2)
public class Bean2 implements LifecycleBean{
@Inject
Bean1 bean1;
@Override
public void start(){
}
}
附:AppLoadEndEvent (即,应用启动完成)
如果初始化时,有些依赖的 Bean 未准备就绪(比如,有些 bean 是在初始化时,才产生的)。可以使用 AppLoadEndEvent 事件:
//注解模式
@Component
public class AppLoadEndListener implements EventListener<AppLoadEndEvent>{
@Override
public void onEvent(AppLoadEndEvent event) throws Throwable {
//db1 init ...
}
}