How to gracefully initialize resources after the Spring container is started

Problem Description:

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

Write the interface of all startup classes

This step can be omitted, because what I want to achieve is that when the container starts, it automatically scans all instances that implement the custom startup interface and calls the initialization method.

package com.chz.apps.common.component;

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

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

}

Writing container startup beans

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;
        }
    }

}

Add ApplicationContext.xml configuration

Add the following configuration at the end of the file:

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

Write the interface implementation class

The rest of the work is related to the business. Write the interface implementation class directly. When the program starts, after loading the Spring container, it will call the StartupListener class above for initialization, and obtain all the interfaces that implement the interface through the SpringContextHolder (requires pre-configuration). bean, call the start method in the bean in turn.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325297772&siteId=291194637