随手記錄9:靜态類中使用spring托管類,自定義加載類
- 簡介
- 項目結構
- 加載方式
-
- 1.通過靜态代碼塊掃描需要加載的類的包路徑
- 2. 通過applicationContext 對象擷取
- 3.通過實作InitializingBean 接口
- controller 中靜态調用
-
- 完整版的 CapitalFileHandleContext
簡介
項目中有很多通用的處理類需要加載到記憶體中;而且實作靜态方法注入使用這些對象内容;這些對象一般有統一的父類(接口/抽象類);需要在項目啟動就将我們指定的對象加載到記憶體中
demo下載下傳
項目結構
裡面需要介紹的類
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);
}
}