Skip to content
标签
spring
字数
1110 字
阅读时间
6 分钟

一、接口方式

系统初始化是、声明一个初始化的接口,然后由一个公共抽象类实现该接口,提供一个初始化的抽象方法。由各初始化任务继承该抽象的公共类

再由一个初始化工厂,获取继承该抽象公共类的所有子类。遍历调用其初始化方法。

该初始化工厂在servelet初始化时调用

初始化接口

java

/**
 * 定义初始化接口。定义初始化和销毁。
 * <i>服务器规范接口</i> 
 */

public interface IInit extends IName{
	/**
	 * 定义初始化接口
	 * @param conf
	 * @author chenli
	 * @data 2016-3-13
	 */
	public void init(ServletConfig conf);
	
	/**
	 * 定义销毁接口
	 * @param conf
	 * @author chenli
	 * @data 2016-3-13
	 */
	public void destroy();
}

抽象公共类

java

/**
 * 出现异常将停止启动
 * @author chenli
 * @date 2016-3-13
 * @version 1.0
 */

public abstract class AbstractInit implements IInit, IPriority, IName {
	private Logger logger = LoggerFactory.getLogger(AbstractInit.class);
	
	
	@Override
	public void init(ServletConfig conf) {
		try {
			doInit(conf);
		} catch (Exception e) {
			if(exitOnException()){
				logger.error("【"+getName()+"】数据初始化异常,应用程序停止...",e);
				System.exit(0);
			}else{
				logger.warn("【"+getName()+"】数据初始化异常,应用程序继续运行...",e);
			}
		}
	}

	/**
	 * 初始化方法
	 * @param conf
	 * @throws Exception
	 * @author chenli
	 * @data 2018-8-15
	 */
	public abstract void doInit(ServletConfig conf) throws Exception;

	
	@Override
	public void destroy() {
		try {
			doDestroy();
		} catch (Exception e) {
			logger.error("【{}】数据销毁异常",getName(),e);
		}
	}
	
	/**
	 * 销毁方法
	 * @param conf
	 * @throws Exception
	 * @author chenli
	 * @data 2018-8-15
	 */
	public abstract void doDestroy();
	/**
	 * 默认异常将停止启动。
	 */
	public boolean exitOnException() {
		return true;
	}
	
	@Override
	public int priority() {
		return PRIORITY_DEAULT;
	}
}

初始化工厂

java

/**
 * 系统配置总工厂
 * @author chenli
 * @date 2016-2-24
 * @version 1.0
 */
@Service
public class InitConfigFactory implements IInit{
	private static final Logger logger = LoggerFactory.getLogger(InitConfigFactory.class);
	private List<AbstractInit> factorys = new ArrayList<AbstractInit>();
	
	@Override
	public String getName() {
		return "系统初始化";
	}
	
	/**
	 * 系统初始化
	 * @author chenli
	 * @data 2016-2-25
	 */
	public void init(ServletConfig conf){
		logger.info("----------------------系统初始化----------------------");
		logger.info("");
		logger.info("#########扫描初始化工厂#########");
		
		List<Class<AbstractInit>> list = ClassUtils.getChilderClass(AbstractInit.class, false);
		for (Class<AbstractInit> c : list) {
			try {
				AbstractInit factory = SpringContext.getBean(c);
				factorys.add(factory);
			} catch (Exception e) {
				logger.error("#	实例化工厂☆☆"+c.getSimpleName()+"☆☆异常,程序运行停止"+c,e);
				System.exit(0);
			}
		}
		Collections.sort(factorys, new PriorityComparator());
		logger.info("#########扫描完成,开始初始化#########");
		logger.info("");
		
		for (AbstractInit f : factorys) {
			logger.info("#########开始初始化【"+f.getName()+"】#########");
			f.init(conf);
			logger.info("#########完成初始化【"+f.getName()+"】#########");
			logger.info("");
			logger.info("");
		}
		
		//初始化权限
		AccessDecisionDao accessDecisionManager = SpringContext.getBean("accessDecisionDao");
		accessDecisionManager.initMenuOptcodeMap();
		logger.info("----------------------系统初始化----------------------");
	}
	
	/**
	 * 系统销毁
	 * @author chenli
	 * @data 2016-2-25
	 */
	public void destroy(){
		logger.info("----------------------系统资源回收----------------------");
		for (AbstractInit f : factorys) {
			logger.info("#########开始销毁系统【"+f.getName()+"】#########");
			f.destroy();
			logger.info("#########完成销毁系统【"+f.getName()+"】#########");
		}
		logger.info("----------------------系统资源回收----------------------");
	}
}

servlet初始化调用

java

/**
 * 所有初始化工作
 * @author chenli
 * @date 2016-1-22
 * @version 1.0
 */
public class InitServlet extends HttpServlet {
	private static final long serialVersionUID = 3117103275293498582L;
	private Logger logger = LoggerFactory.getLogger(InitServlet.class);
	private InitConfigFactory configFacroty;
	
	public void init(ServletConfig config) throws ServletException {
		logger.info("InitServlet init start");

		long start = System.currentTimeMillis();
		//初始化SpringContext容器
		SpringContext.initContext(config.getServletContext());
		
		//系统初始化
		configFacroty = SpringContext.getBean(InitConfigFactory.class);
		configFacroty.init(config);
		// 系统内存监控
		MemoryMonitorUtil.startGcUsageMonitor();
		super.init(config);
		logger.info("InitServlet init completed in {}ms",(System.currentTimeMillis()-start));
	}
	
	public void destroy() {
		logger.info("InitServlet destroy.....");
		
		//系统初始化
		configFacroty.destroy();
		super.destroy();
	}
	
}

二、方式二

通过注解方式,参考@PostConstruct与@PreDestroy

@PostConstruct

@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

在整个Bean初始化中的执行顺序:

Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

例子:

java
@Autowired
private SysDictTypeMapper dictTypeMapper;

@Autowired
private SysDictDataMapper dictDataMapper;

/**
* 项目启动时,初始化字典到缓存
*/
@PostConstruct
public void init(){
    List<SysDictType> dictTypeList = dictTypeMapper.selectDictTypeAll();
    for (SysDictType dictType : dictTypeList){
        List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
        DictUtils.setDictCache(dictType.getDictType(), dictDatas);
    }
}

@PreDestroy

被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

java
/**
 * 确保应用退出时能关闭后台线程
 *
 * @author ruoyi
 */
@Component
public class ShutdownManager {
    private static final Logger logger = LoggerFactory.getLogger("sys-user");

    @PreDestroy
    public void destroy() {
        shutdownAsyncManager();
    }

    /**
     * 停止异步执行任务
     */
    private void shutdownAsyncManager() {
        try {
            logger.info("====关闭后台任务任务线程池====");
            AsyncManager.me().shutdown();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }
}