天天看點

随手記錄9:項目啟動加載類到靜态實作靜态方法調用.簡介項目結構加載方式controller 中靜态調用

随手記錄9:靜态類中使用spring托管類,自定義加載類

  • 簡介
  • 項目結構
  • 加載方式
    • 1.通過靜态代碼塊掃描需要加載的類的包路徑
    • 2. 通過applicationContext 對象擷取
    • 3.通過實作InitializingBean 接口
  • controller 中靜态調用
    • 完整版的 CapitalFileHandleContext

簡介

項目中有很多通用的處理類需要加載到記憶體中;而且實作靜态方法注入使用這些對象内容;這些對象一般有統一的父類(接口/抽象類);需要在項目啟動就将我們指定的對象加載到記憶體中

demo下載下傳

項目結構

随手記錄9:項目啟動加載類到靜态實作靜态方法調用.簡介項目結構加載方式controller 中靜态調用
裡面需要介紹的類
1. CapitalFileHandleContext對外暴露靜态方法 裡面有個靜态的map通過capitalNo擷取真正的執行的類
2. BaseCapitalFileHandle這個是底層的基類接口 提供對應的方法
3. AbstractBaseCapitalFileHandle 抽象類 提供抽象方法
4. XinWangCapitalFileHandle/NongShangCapitalFileHandle 具體的實作類内容;
5. ClassFinder 就是一個工具類掃描指定包路徑下面的所有的class對象;在靜态代碼塊中加載到記憶體中去
           

加載方式

1.通過靜态代碼塊掃描需要加載的類的包路徑

靜态代碼塊中通過我們指定的包路徑進行掃描擷取到所有的class類檔案然後加到到本地
通過Class.newInstance 建立對象 然後根據capitalNo 擷取不到類型的設定到Map容器中
這種方式不需要将初始化對象交給spring管理簡單 清爽;
           
public class CapitalFileHandleContext{
    private ApplicationContext applicationContext;
	private static Logger logger = LoggerFactory.getLogger(CapitalFileHandleContext.class);
	private static final String DEFAULT_PACKAGE = "com.khy.handle.impl";//指定掃描某個包路徑下面的全部class類

	//加載方式1-->通過靜态代碼塊;指定加載代碼中某個包路徑下面的類,然後完成對應方法的調用;
    public static Map<String,BaseCapitalFileHandle>map = new ConcurrentHashMap<>();

    static{
    	logger.info("init 初始化 BaseCapitalFileHandle 的相關接口内容...");
      	if(map.isEmpty()){
      		//擷取目前包下面所有符合條件的類
			Set<Class<?>> classes = ClassFinder.getClasses(DEFAULT_PACKAGE);
			Iterator<Class<?>> iter = classes.iterator();
			while(iter.hasNext()){ 
				Class<?> clz = iter.next();
				if(BaseCapitalFileHandle.class.isAssignableFrom(clz)){
					BaseCapitalFileHandle processor = null;
					try {
						processor = (BaseCapitalFileHandle)clz.newInstance();
					} catch (InstantiationException e) {
						logger.error("初始化 BaseCapitalFileHandle 處理者工廠反射建立執行個體失敗...退出",e);
						System.exit(-1);
					} catch (IllegalAccessException e) {
						logger.error("初始化 BaseCapitalFileHandle 處理者工廠反射建立執行個體失敗...退出",e);
						System.exit(-1);
					}
					map.put(processor.getCapitalNo(), processor);
				}
			}
			logger.info("BaseCapitalFileHandle 初始化完畢...共加載{}種處理者",map.size());
		}
    }
}
           

2. 通過applicationContext 對象擷取

需要通過CapitalFileHandleContext  添加 @Component 被spring 掃描加載 然後通過實作 ApplicationContextAware類,實作setApplicationContext 方法 擷取ApplicationContext 
通過@PostConstruct 在spring初始化完成之後 可以通過applicationContext擷取spring中所有符合條件的實作類然後處理  這種需要将對象交給spring管理;
           
@Component
public class CapitalFileHandleContext implements ApplicationContextAware{
    private ApplicationContext applicationContext;
    
    //加載方式2-->通過@PostConstruct 注解然後在spring 加載完類之後調用該方法從applicationContext中擷取需要加載的類内容然後完成類的加載
    public static Map<String,BaseCapitalFileHandle>map2 = new ConcurrentHashMap<>();
    @PostConstruct
    public void init2(){
    	logger.info("init2 初始化 BaseCapitalFileHandle的相關接口内容...");
    	if(map2.isEmpty()){
    		try {
    			Map<String, BaseCapitalFileHandle> baseResultNotifyHandlers = applicationContext.getBeansOfType(BaseCapitalFileHandle.class);
    			if(MapUtils.isNotEmpty(baseResultNotifyHandlers)){
    				baseResultNotifyHandlers.entrySet().stream().forEach(e->{
    					map2.put(e.getValue().getCapitalNo(), e.getValue());
    				});
    			}
    		} catch (Exception e) {
    			logger.error("初始化資方檔案處理類執行個體失敗...退出"+e.getMessage(),e);
    			System.exit(-1);
    		}
    		logger.info("BaseCapitalFileHandle初始化完畢...共加載{}種處理者",map.size());
    	}
    } 
    
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
}
           

3.通過實作InitializingBean 接口

需要加載的類實作 InitializingBean 接口 afterPropertiesSet方法 ;然後将對象設定到CapitalFileHandleContext 中的maps容器中去;也需要将對象交給spring管理 但是比方式二要簡單 而且CapitalFileHandleContext 不要交給spring管理.
           
public class CapitalFileHandleContext{
	//加載方式3-->通過抽象類實作InitializingBean 在spring初始化完類調用afterPropertiesSet方法裡面完成具體的操作内容;
    public static Map<String,BaseCapitalFileHandle>map3 = new ConcurrentHashMap<>();
   
}

public abstract class AbstractBaseCapitalFileHandle implements BaseCapitalFileHandle,InitializingBean {

	public abstract <T>void capitalHandleFile(T t);
	
	@Override
	public <T> void handleFile(T t) {
		capitalHandleFile(t);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		CapitalFileHandleContext.map3.put(getCapitalNo(), this);
	}
}
           

controller 中靜态調用

@RestController
@RequestMapping("loadBean")
public class LoadBeanController {

	@RequestMapping("get")
	public String test(String type){
		JSONObject json = new JSONObject();
		CapitalFileHandleContext.handleFile(type, json);
		return "LoadBeanController 方法執行完畢";
	}
}

           

完整版的 CapitalFileHandleContext

package com.khy.handle;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import com.khy.utils.ClassFinder;
@Component
public class CapitalFileHandleContext implements ApplicationContextAware{
    private ApplicationContext applicationContext;
	private static Logger logger = LoggerFactory.getLogger(CapitalFileHandleContext.class);
	private static final String DEFAULT_PACKAGE = "com.khy.handle.impl";//指定掃描某個包路徑下面的全部class類

	//加載方式1-->通過靜态代碼塊;指定加載代碼中某個包路徑下面的類,然後完成對應方法的調用;
    public static Map<String,BaseCapitalFileHandle>map = new ConcurrentHashMap<>();
    //加載方式3-->通過抽象類實作InitializingBean 在spring初始化完類調用afterPropertiesSet方法裡面完成具體的操作内容;
    public static Map<String,BaseCapitalFileHandle>map3 = new ConcurrentHashMap<>();

    static{
    	logger.info("init 初始化 BaseCapitalFileHandle的相關接口内容...");
      	if(map.isEmpty()){
			Set<Class<?>> classes = ClassFinder.getClasses(DEFAULT_PACKAGE);
			Iterator<Class<?>> iter = classes.iterator();
			while(iter.hasNext()){ 
				Class<?> clz = iter.next();
				if(BaseCapitalFileHandle.class.isAssignableFrom(clz)){
					BaseCapitalFileHandle processor = null;
					try {
						processor = (BaseCapitalFileHandle)clz.newInstance();
					} catch (InstantiationException e) {
						logger.error("初始化 BaseInterface 處理者工廠反射建立執行個體失敗...退出",e);
						System.exit(-1);
					} catch (IllegalAccessException e) {
						logger.error("初始化BaseInterface處理者工廠反射建立執行個體失敗...退出",e);
						System.exit(-1);
					}
					map.put(processor.getCapitalNo(), processor);
				}
			}
			logger.info("BaseInterface處理工廠初始化完畢...共加載{}種處理者",map.size());
		}
    }
    
    //加載方式2-->通過@PostConstruct 注解然後在spring 加載完類之後調用該方法從applicationContext中擷取需要加載的類内容然後完成類的加載
    public static Map<String,BaseCapitalFileHandle>map2 = new ConcurrentHashMap<>();
    @PostConstruct
    public void init2(){
    	logger.info("init2 初始化 BaseCapitalFileHandle的相關接口内容...");
    	if(map2.isEmpty()){
    		try {
    			Map<String, BaseCapitalFileHandle> baseResultNotifyHandlers = applicationContext.getBeansOfType(BaseCapitalFileHandle.class);
    			if(MapUtils.isNotEmpty(baseResultNotifyHandlers)){
    				baseResultNotifyHandlers.entrySet().stream().forEach(e->{
    					map2.put(e.getValue().getCapitalNo(), e.getValue());
    				});
    			}
    		} catch (Exception e) {
    			logger.error("初始化資方檔案處理類執行個體失敗...退出"+e.getMessage(),e);
    			System.exit(-1);
    		}
    		logger.info("BaseCapitalFileHandle初始化完畢...共加載{}種處理者",map.size());
    	}
    } 
    
    
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	public static <T>void handleFile(String capitalNo, T t) {
		Assert.hasText(capitalNo, "擷取檔案處理類capitalNo不為空capitalNo="+capitalNo);
		BaseCapitalFileHandle capitalFileHandle = map.get(capitalNo);
		Assert.notNull(capitalFileHandle, "未擷取到檔案處理類capitalNo="+capitalNo);
		capitalFileHandle.handleFile(t);
		
		capitalFileHandle = map2.get(capitalNo);
		Assert.notNull(capitalFileHandle, "未擷取到檔案處理類capitalNo="+capitalNo);
		capitalFileHandle.handleFile(t);
		
		capitalFileHandle = map3.get(capitalNo);
		Assert.notNull(capitalFileHandle, "未擷取到檔案處理類capitalNo="+capitalNo);
		capitalFileHandle.handleFile(t);
		
	}

}