随手记录9:项目启动加载类到静态实现静态方法调用.

简介

项目中有很多通用的处理类需要加载到内存中;而且实现静态方法注入使用这些对象内容;这些对象一般有统一的父类(接口/抽象类);需要在项目启动就将我们指定的对象加载到内存中
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);
		
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值