如何优雅的在Spring容器启动完成后进行资源初始化

问题描述:

经常遇到这样的场景:希望容器启动的时候,进行一些初始化等操作。一般的做法就是通过Spring的bean set方式或者@PostConstruct注解来解决;
很多人使用@ PostConstruct或者@Component的时候,经常出现Spring容器里面的bean(尤其是数据库操作相关的bean)还没有启动完全,自己需要初始化的bean代码已经调用。
下面是一个自己使用的方法,也许不是最优的方案,但是是经过了实践考验的。

编写所有启动类的接口

这一步可以省略,因为我要实现的是,容器启动的时候,自动扫描所有实现了自定义启动接口的实例,并调用初始化方法。

package com.chz.apps.common.component;

/**
 * 自启动接口类,容器启动完成后,自动调用启动方法
 */
public interface IAutoStartPlugin {

    /**
     * 启动
     */
    void start();

}

编写容器启动bean

package com.chz.component.basic.listener;

import com.chz.apps.common.component.IAutoStartPlugin;
import com.chz.component.basic.configure.SpringContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {

    private static Boolean loaded = false;//启动标记,确保只启动过一次

    @Autowired
    private DicPlugin dicPlugin;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if(event.getApplicationContext().getParent() != null && !loaded){
            Map<String,IAutoStartPlugin> allPlugin = SpringContextHolder.getApplicationContext().getBeansOfType(IAutoStartPlugin.class);
            if(allPlugin != null || allPlugin.size() > 0){
                for (Map.Entry<String,IAutoStartPlugin> row : allPlugin.entrySet()) {
                    row.getValue().start();//调用启动类
                }
            }
            loaded = true;
        }
    }

}

添加ApplicationContext.xml配置

在文件的最后加上如下配置:

<bean id="afterStartupListener" class="com.chz.component.basic.listener.StartupListener" /><!-- 启动容器后执行的方法 -->

编写接口实现类即可

剩下的工作就与业务有关了,直接编写接口实现类,程序在启动的时候,加载完Spring容器后,会调用上面的StartupListener类进行初始化,通过SpringContextHolder(需要预先配置)获取所有实现了接口的bean,依次调用bean里面的start方法。

猜你喜欢

转载自my.oschina.net/yyqz/blog/1807162
今日推荐