package com.pab.cc.aplus.ams.service.common.h2.ioc;
import com.pab.cc.aplus.ams.service.common.h2.mybatis.MyBatisHelper;
import com.pab.cc.aplus.ams.service.common.h2.util.AnnotationUtil;
import com.pab.cc.aplus.ams.service.common.h2.util.BeanNameUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
* bean 加载器
*/
public class BeanDefinitionLoader {
private static Logger logger = LoggerFactory.getLogger(BeanDefinitionLoader.class);
/**
* 加载所有的bean定义
*/
public static void loadAllBeanDefinition(String packageName) {
logger.info("开始扫描【" + packageName + "】下的所有的类名...");
// 扫描所有的类名
List<String> classNameList;
try {
classNameList = PackageUtil.getClassName(packageName);
// 去重
classNameList = new ArrayList<>(new HashSet<>(classNameList));
} catch (IOException e) {
throw new RuntimeException(e);
}
if (CollectionUtils.isEmpty(classNameList)) {
throw new RuntimeException("com.pab包下没有java类");
}
for (String className : classNameList) {
logger.info("类名: {}", className);
}
logger.info("扫描【" + packageName + "】下的所有的类名结束,开始获取所有的类对象...");
// 获取所有的类对象
List<Class> classList = new ArrayList<>(classNameList.size());
if (CollectionUtils.isNotEmpty(classNameList)) {
for (String c : classNameList) {
try {
classList.add(Class.forName(c));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
ClassHolder.classList.addAll(classList);
logger.info("获取所有的类对象结束,加载普通bean定义(类上加了@Service @Component @Repository @Configuration注解的bean)...");
// 加载bean定义 TODO 一个类上即有Service又有Component的情况没有做校验
for (Class clazz : classList) {
Annotation[] annotations = clazz.getAnnotations();
Annotation annotation = AnnotationUtil.getOneOfAnnotation(annotations, Service.class, Component.class, Repository.class, Configuration.class);
if (annotation != null) {
String beanName = null;
// bean名称使用自定义的
if (annotation.annotationType().equals(Service.class)){
beanName = ((Service)annotation).value();
} else if (annotation.annotationType().equals(Component.class)){
beanName = ((Component)annotation).value();
} else if (annotation.annotationType().equals(Repository.class)){
beanName = ((Repository)annotation).value();
} else if (annotation.annotationType().equals(Configuration.class)){
beanName = ((Configuration)annotation).value();
}
if (StringUtils.isEmpty(beanName)) {
//bean名称使用默认名称
beanName = BeanNameUtil.getDefaultBeanNameByClass(clazz);
}
if (BeanDefinitionHolder.get(beanName) != null) {
String possibleReason = "请检查:类名,javaConfigBean方法名,指定的名称";
throw new RuntimeException("定义了多个同名Bean:【"+beanName+"】" + possibleReason);
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanName(beanName);
beanDefinition.setBeanClass(clazz);
BeanDefinitionHolder.put(beanName,beanDefinition);
}
}
logger.info("加载普通bean定义结束,开始加载JavaConfig bean定义...");
// 收集所有的@Bean的定义
for (Map.Entry<String, BeanDefinition> entry : BeanDefinitionHolder.getBeanDefinitionMap().entrySet()) {
BeanDefinition value = entry.getValue();
Annotation annotation = AnnotationUtil.getAnnotationByAnnotationClass(value.getBeanClass().getAnnotations(), Configuration.class);
if (annotation != null) {
// 查找所有的加了@Bean的method,注入参数,执行生成Bean
Method[] methods = value.getBeanClass().getDeclaredMethods();
for (Method method : methods) {
Annotation[] methodAnnotations = method.getAnnotations();
Annotation beanAnnotation = AnnotationUtil.getOneOfAnnotation(methodAnnotations, Bean.class);
if (beanAnnotation != null) {
String beanName = null;
String[] beanNames = ((Bean)beanAnnotation).value();
if (beanNames.length > 0) {
beanName = beanNames[0];
} else {
beanNames = ((Bean)beanAnnotation).name();
if (beanNames.length > 0) {
beanName = beanNames[0];
}
}
// 默认取第一个
if (StringUtils.isEmpty(beanName)) {
beanName = method.getName();
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanName(beanName);
beanDefinition.setBeanClass(method.getReturnType());
beanDefinition.setConfigurationFlag(true);
beanDefinition.setJavaConfigBeanMethod(method);
beanDefinition.setConfigurationBeanDefinitionName(value.getBeanName());
BeanDefinitionHolder.put(method.getName(), beanDefinition);
}
}
}
}
}
/**
* 递归创建Bean定义 TODO 还不能解决循环依赖,如果有循环依赖会StackOverFlow
*
* @param clazz
* @param dependencyBeanDefinitionList
* @return
*/
public static BeanDefinition createAndPutBeanDefinition(Class clazz, List<BeanDefinition> dependencyBeanDefinitionList) {
String classDefaultBeanName = BeanNameUtil.getDefaultBeanNameByClass(clazz);
if (BeanDefinitionHolder.get(classDefaultBeanName) != null) {
logger.info("BeanDefinitionHolder中已存在:{}", classDefaultBeanName);
return BeanDefinitionHolder.get(classDefaultBeanName);
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanName(classDefaultBeanName);
beanDefinition.setBeanClass(clazz);
// 查询依赖的bean的定义
// if (dependencyBeanDefinitionList == null) {
// dependencyBeanDefinitionList = new ArrayList<>();
// }
// Field[] fields = clazz.getDeclaredFields();
// if (fields != null && fields.length > 0) {
// for (Field field : fields) {
// Annotation[] annotations = field.getAnnotations();
// if (AnnotationUtil.containAnnotation(annotations, Autowired.class)) {
// Class fieldClass = field.getType();
// String defaultBeanName = BeanNameUtil.getDefaultBeanNameByClass(fieldClass);
// if (AnnotationUtil.containAnnotation(annotations, Qualifier.class)) {
// // 取Qualifier指定的bean
// Qualifier qualifier = (Qualifier) AnnotationUtil.getAnnotationByAnnotationClass(annotations, Qualifier.class);
// String value = qualifier.value();
// if (StringUtils.isBlank(value)) {
// throw new RuntimeException(clazz.getSimpleName() + "的Qualifier指定的value为空");
// }
// defaultBeanName = value;
// }
// BeanDefinition dependencyDefinition = BeanDefinitionHolder.get(defaultBeanName);
// if (dependencyDefinition == null) {
// dependencyDefinition = createAndPutBeanDefinition(field.getType(), dependencyBeanDefinitionList);
// }
// BeanDefinitionHolder.put(defaultBeanName, beanDefinition);
// dependencyBeanDefinitionList.add(dependencyDefinition);
// }
// // TODO 处理其它注解,不光有Autowired...
// }
// }
// beanDefinition.setDependencyBeanDefinitionList(dependencyBeanDefinitionList);
// 放入BeanDefinitionMap中
BeanDefinitionHolder.put(classDefaultBeanName, beanDefinition);
return beanDefinition;
}
/**
* 更新javaConfig Bean定义,主要加载依赖bean TODO 还不能解决循环依赖,如果有循环依赖会StackOverFlow
*
* @param clazz
* @param dependencyBeanDefinitionList
* @return
*/
public static BeanDefinition updateJavaConfigBeanDefinition(Class clazz, String classDefaultBeanName, List<BeanDefinition> dependencyBeanDefinitionList) {
BeanDefinition beanDefinition = BeanDefinitionHolder.get(classDefaultBeanName);
beanDefinition.setBeanName(classDefaultBeanName);
beanDefinition.setBeanClass(clazz);
// 查询依赖的bean的定义
if (dependencyBeanDefinitionList == null) {
dependencyBeanDefinitionList = new ArrayList<>();
}
Field[] fields = clazz.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
Annotation[] annotations = field.getAnnotations();
if (AnnotationUtil.containAnnotation(annotations, Autowired.class)) {
Class fieldClass = field.getType();
String defaultBeanName = BeanNameUtil.getDefaultBeanNameByClass(fieldClass);
if (AnnotationUtil.containAnnotation(annotations, Qualifier.class)) {
// 取Qualifier指定的bean
Qualifier qualifier = (Qualifier) AnnotationUtil.getAnnotationByAnnotationClass(annotations, Qualifier.class);
String value = qualifier.value();
if (StringUtils.isBlank(value)) {
throw new RuntimeException(clazz.getSimpleName() + "的Qualifier指定的value为空");
}
defaultBeanName = value;
}
BeanDefinition dependencyDefinition = BeanDefinitionHolder.get(defaultBeanName);
// 获取不到bean应该抛异常
if (dependencyDefinition == null) {
// TODO 依赖其它javaConfigBean的时候其它javaConfigBean没有加载可能也是Null
// throw new RuntimeException("无法获取bean定义: 【" + clazz.getSimpleName() + "】中的【" + defaultBeanName + "】, 请确认包扫描范围是否正确!");
if ("Dao".equals(fieldClass.getSimpleName().substring(fieldClass.getSimpleName().length()-3))) {
try {
//TODO 不光有Dao还有别的,临时处理有点low后面改
fieldClass = Class.forName("com.pab.cc.aplus.ams.infrastructure.dao.impl." + fieldClass.getSimpleName() + "Impl");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
dependencyDefinition = createAndPutBeanDefinition(fieldClass, null);//如果这个bean在Config中就不行了,这还有bug
}
// BeanDefinitionHolder.put(defaultBeanName, beanDefinition);
dependencyBeanDefinitionList.add(dependencyDefinition);
}
// TODO 处理其它注解,不光有Autowired...
}
}
// beanDefinition.setDependencyBeanDefinitionList(dependencyBeanDefinitionList);
// 放入BeanDefinitionMap中
BeanDefinitionHolder.put(classDefaultBeanName, beanDefinition);
return beanDefinition;
}
/**
* 加载MyBatisBean
*/
@SuppressWarnings("unchecked")
public static void loadMyBatisBean() {
// 加载Repository
logger.info("开始加载加载Repository BeanDefinition");
loadAllBeanDefinition("com.pab.cc.aplus.ams.infrastructure.dao.impl");
// 加载 repository包下的bean
loadAllBeanDefinition("com.pab.cc.aplus.ams.repository.impl");
// 加载SqlSessionFactory
logger.info("开始加载SqlSessionFactory");
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanName("sqlSessionFactory");
beanDefinition.setBeanClass(SqlSessionFactory.class);
BeanDefinitionHolder.put("sqlSessionFactory", beanDefinition);
// 实例化SqlSessionFactory
logger.info("实例化SqlSessionFactory");
BeanHolder.put("sqlSessionFactory", MyBatisHelper.getSqlSessionFactory());
BeanHolder.put(SqlSessionFactory.class, MyBatisHelper.getSqlSessionFactory());
}
}
package com.pab.cc.aplus.ams.service.common.h2.ioc;
import com.pab.cc.aplus.ams.common.util.DateTimeUtil;
import com.pab.cc.aplus.ams.service.common.h2.mybatis.MyBatisHelper;
import com.pab.cc.aplus.ams.service.common.h2.util.AnnotationUtil;
import com.pab.cc.aplus.ams.service.common.h2.util.BeanNameUtil;
import com.pab.cc.aplus.base.db.dao.core.configuration.DataSourceConfigProperties;
import com.pab.cc.aplus.base.db.dao.core.dao.impl.AbstractBaseDaoImpl;
import com.pab.cc.aplus.base.db.dao.core.dao.impl.AbstractEntityDaoImpl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static com.pab.cc.aplus.ams.common.util.DateTimeUtil.DATE_PATTERN_YYYYMMDD_HHMMSS;
/**
* Bean实例化工具
*
* @version 1.0
* @date 2019/11/9 11:16
*/
public class BeanInstant {
private static Logger logger = LoggerFactory.getLogger(BeanInstant.class);
/**
* 实例化所有的Bean对象
*/
public static void instantAllBean() {
logger.info("开始实例化所有的bean,开始时间:" + DateTimeUtil.formatDate(new Date(), DATE_PATTERN_YYYYMMDD_HHMMSS));
for (Map.Entry<String, BeanDefinition> entry : BeanDefinitionHolder.getBeanDefinitionMap().entrySet()) {
instantBean(entry.getValue());
logger.info("实例化bean:{}完成", entry.getValue().getBeanName());
}
logger.info("实例化所有的bean结束,结束时间:" + DateTimeUtil.formatDate(new Date(), DATE_PATTERN_YYYYMMDD_HHMMSS));
}
/**
* 实例化bean对象
*
* @param beanDefinition bean定义
* @return Object
*/
private static Object instantBean(BeanDefinition beanDefinition) {
logger.info("开始实例化 {}", beanDefinition.getBeanName());
Object bean = BeanHolder.get(beanDefinition.getBeanName());
// TODO 临时处理
if (beanDefinition.getBeanName().equals("sqlSessionFactory")) {
return bean;
}
if (bean != null) {
// return bean;
} else {
// 实例化普通bean 如用@Component,@Service注解的
Class clazz = beanDefinition.getBeanClass();
if (!beanDefinition.isConfigurationFlag()) {
try {
bean = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("实例化bean:" + clazz.getSimpleName() + "失败", e);
}
// 创建好的bean放入容器
BeanHolder.put(clazz, bean);
BeanHolder.put(beanDefinition.getBeanName(), bean);
fieldInject(bean);
// 注入依赖属性
// Field[] fields = clazz.getDeclaredFields();
// if (fields != null && fields.length > 0) {
// for (Field field : fields) {
// Annotation[] annotations = field.getAnnotations();
// if (AnnotationUtil.containAnnotation(annotations, Autowired.class)) {
// Class fieldClass = field.getType();
// String defaultBeanName = BeanNameUtil.getDefaultBeanNameByClass(fieldClass);
// if (AnnotationUtil.containAnnotation(annotations, Qualifier.class)) {
// // 取Qualifier指定的bean
// Qualifier qualifier = (Qualifier) AnnotationUtil.getAnnotationByAnnotationClass(annotations, Qualifier.class);
// String value = qualifier.value();
// if (StringUtils.isBlank(value)) {
// throw new RuntimeException(clazz.getSimpleName() + "的Qualifier指定的value为空");
// }
// defaultBeanName = value;
// }
// BeanDefinition dependencyDefinition = BeanDefinitionHolder.get(defaultBeanName);
// if (dependencyDefinition == null) {
// throw new RuntimeException("找不到"+ clazz.getSimpleName() + "中的【" + field.getName() +"】对应的bean【" + defaultBeanName + "】");
// }
// // 注入Bean
// logger.info("【{}】 注入依赖: 【{}】", beanDefinition.getBeanName(), dependencyDefinition.getBeanName());
// Object dependencyBean = instantBean(dependencyDefinition);
// field.setAccessible(true);
// try {
// field.set(bean, dependencyBean);
// } catch (IllegalAccessException e) {
// throw new RuntimeException(e);
// }
// }
// // TODO 处理其它注解,不光有Autowired...
// }
// }
} else {
// 实例化javaConfigBean
// 参数bean注入,只支持@Qualifier
Method method = beanDefinition.getJavaConfigBeanMethod();
logger.info("开始实例化javaConfigBean:{}", beanDefinition.getBeanName() + ", methodName:" + method.getName());
Parameter[] parameters = method.getParameters();
Object[] params = new Object[parameters.length];
int i = 0;
if (parameters.length > 0) {
for (Parameter parameter : parameters) {
Annotation[] parameterAnnotations = parameter.getAnnotations();
if (parameterAnnotations.length != 1) {
throw new RuntimeException(method.getName() + "javaConfig方法参数只支持一个Qualifier注解");
}
if (parameterAnnotations[0].annotationType().equals(Qualifier.class)) {
Qualifier qualifier = (Qualifier) parameterAnnotations[0];
Object parameterBean = BeanHolder.get(qualifier.value());
if (parameterBean == null) {
BeanDefinition paramBeanDefinition = BeanDefinitionHolder.getBeanDefinitionMap().get(qualifier.value());
if (paramBeanDefinition == null) {
throw new RuntimeException("类:" + clazz.getSimpleName() + "中的:" + method.getName() + "方法参数" + qualifier.value() + "在容器中不存在");
} else {
// 递归实例化方法参数bean
logger.info("{}递归实例化方法参数bean: {}", beanDefinition.getBeanName(), paramBeanDefinition.getBeanName());
parameterBean = instantBean(paramBeanDefinition);
}
}
params[i++] = parameterBean;
} else {
throw new RuntimeException(method.getName() + " 方法参数必须加@Qualifier注解或为空");
}
}
}
Object javaConfigBean;
// 获取configuration配置类
String defConfBeanName = beanDefinition.getConfigurationBeanDefinitionName();
Object configurationBean = BeanHolder.get(defConfBeanName);
if (configurationBean == null) {
BeanDefinition confBeanDefinition = BeanDefinitionHolder.getBeanDefinitionMap().get(defConfBeanName);
configurationBean = instantBean(confBeanDefinition);
}
try {
logger.info("实例化javaConfigBean : {}", beanDefinition.getBeanName());
javaConfigBean = method.invoke(configurationBean, params);
} catch (Exception e) {
throw new RuntimeException("方法" + method.getName() + "执行失败", e);
}
// 创建好的bean放入容器
BeanHolder.put(javaConfigBean.getClass(), javaConfigBean);
BeanHolder.put(beanDefinition.getBeanName(), javaConfigBean);
// 注入后绑定的Bean
Class methodReturnClass = javaConfigBean.getClass();
BeanDefinition methodReturnBeanDefinition = BeanDefinitionHolder.getBeanDefinitionMap().get(method.getName());
if (methodReturnBeanDefinition == null) {
throw new RuntimeException("类:" + methodReturnClass.getSimpleName() + "定义不存在: " + BeanNameUtil.getDefaultBeanNameByClass(methodReturnClass));
}
fieldInject(javaConfigBean);
bean = javaConfigBean;
}
logger.info("实例化:{} 结束", beanDefinition.getBeanName());
// return bean;
}
//TODO 还没有实现setter注入,所以把实现 了AbstractBaseDaoImpl接口的dao 注入sqlSession
if (AbstractBaseDaoImpl.class.isAssignableFrom(bean.getClass())) {
logger.info(beanDefinition.getBeanName() + "注入sqlSession");
((AbstractBaseDaoImpl) bean).setSqlSessionFactory(MyBatisHelper.getSqlSessionFactory());
if (AbstractEntityDaoImpl.class.isAssignableFrom(bean.getClass())) {
Class clazz = bean.getClass();
// TODO 此处直接获取父类,有点low
Field[] fields = clazz.getSuperclass().getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
if (field.getName().equals("dataSourceConfigProperties")) {
field.setAccessible(true);
try {
DataSourceConfigProperties dataSourceConfigProperties = new DataSourceConfigProperties();
dataSourceConfigProperties.setDialect(null);
dataSourceConfigProperties.setInterceptors(null);
dataSourceConfigProperties.setMybatisMapper(null);
dataSourceConfigProperties.setTypeHandlers(null);
field.set(bean, new DataSourceConfigProperties());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
// 调用afterPropertiesSet方法
logger.info("调用afterPropertiesSet方法");
if (InitializingBean.class.isAssignableFrom(bean.getClass())) {
Method afterPropertiesSetMethod;
try {
afterPropertiesSetMethod = bean.getClass().getMethod("afterPropertiesSet");
} catch (NoSuchMethodException e) {
throw new RuntimeException("类" + beanDefinition.getBeanName() + "实现了InitializingBean接口但是没有afterPropertiesSet方法");
}
try {
afterPropertiesSetMethod.invoke(bean);
} catch (Exception e) {
throw new RuntimeException("afterPropertiesSet方法执行失败", e);
}
}
// TODO 执行PostConstruct方法
return bean;
}
public static void fieldInject(Object bean) {
Class clazz = bean.getClass();
Field[] fields = clazz.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
Annotation[] annotations = field.getAnnotations();
if (AnnotationUtil.containAnnotation(annotations, Autowired.class)) {
Class fieldClass = field.getType();
String defaultBeanName;
if (AnnotationUtil.containAnnotation(annotations, Qualifier.class)) {
// 取Qualifier指定的bean
Qualifier qualifier = (Qualifier) AnnotationUtil.getAnnotationByAnnotationClass(annotations, Qualifier.class);
String value = qualifier.value();
if (StringUtils.isBlank(value)) {
throw new RuntimeException(clazz.getSimpleName() + "的Qualifier指定的value为空");
}
defaultBeanName = value;
} else {
defaultBeanName = BeanNameUtil.getDefaultBeanNameByClass(fieldClass);
}
BeanDefinition dependencyDefinition = BeanDefinitionHolder.get(defaultBeanName);
if (dependencyDefinition == null) {
// 如果依赖是接口的话查询实现类
if (fieldClass.isInterface()) {
List<Class> classList = ClassHolder.getImplClass(fieldClass);
if (classList == null || classList.size() == 0) {
throw new RuntimeException("找不到" + fieldClass.getSimpleName() + "的实现类");
}
else if (classList.size() > 1) {
throw new RuntimeException("实现类" + fieldClass.getSimpleName() + "的个数不唯一");
}
dependencyDefinition = BeanDefinitionHolder.getSingleBeanDefinitionByClass(classList.get(0));
} else {
throw new RuntimeException("找不到"+ clazz.getSimpleName() + "中的【" + field.getName() +"】对应的bean【" + defaultBeanName + "】");
}
}
// 注入Bean
logger.info("【{}】 注入依赖: 【{}】", clazz.getSimpleName(), dependencyDefinition.getBeanName());
Object dependencyBean = instantBean(dependencyDefinition);
field.setAccessible(true);
try {
field.set(bean, dependencyBean);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
// TODO 处理其它注解,不光有Autowired...
}
}
}
}
package com.pab.cc.aplus.ams.service.common.h2.ioc;
import java.lang.annotation.Annotation;
public class Util {
/**
* 类上包含指定的Annotation
*
* @param clazz
* @param annotation
* @return
*/
public static boolean classContainAnnotation(Class clazz, Annotation annotation) {
if (annotation == null) {
return false;
}
Annotation[] annotations = clazz.getAnnotations();
if (annotations != null && annotations.length > 0) {
for (Annotation a : annotations) {
if (a.annotationType().equals(annotation.annotationType())) {
return true;
}
}
}
return false;
}
/**
* 判断一个类是否为另一个类的子类
*
* @param childClass 子类
* @param parentClass 父类
* @return boolean
*/
public static boolean isSubClass(Class childClass, Class parentClass) {
try {
childClass.asSubclass(parentClass);
return true;
} catch (Exception e) {
return false;
}
}
}
package com.pab.cc.aplus.ams.service.common.h2.ioc;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class PackageUtil {
// public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
//
// List<String> names = getClassName("com.pab.cc.aplus.ams.statement");
for (String s : names) {
System.out.println(s);
}
//
// Class clazz = Class.forName("com.pab.cc.aplus.ams.service.common.h2.util.StatementUtil");
// Object object = clazz.newInstance();
//
// System.out.println(((StatementUtil)object).convertNullToZero(BigDecimal.ZERO));
// }
/**
* 获取某包下(包括该包的所有子包)所有类
*
* @param packageName 包名
* @return 类的完整名称
* @throws
*/
public static List<String> getClassName(String packageName) throws IOException {
return getClassName(packageName, true);
}
/**
* 获取某包下所有类
*
* @param packageName 包名
* @param childPackage 是否遍历子包
* @return 类的完整名称
* @throws
*/
public static List<String> getClassName(String packageName, boolean childPackage) throws IOException {
List<String> fileNames = new ArrayList<>();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String packagePath = packageName.replace(".", "/");
Enumeration<URL> urls = loader.getResources(packagePath);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url == null)
continue;
String type = url.getProtocol();
if (type.equals("file")) {
fileNames.addAll(getClassNameByFile(url.getPath(), childPackage));
} else if (type.equals("jar")) {
fileNames.addAll(getClassNameByJar(url.getPath(), childPackage));
}
}
fileNames.addAll(getClassNameByJars(((URLClassLoader) loader).getURLs(), packagePath, childPackage));
return fileNames;
}
/**
* 从项目文件获取某包下所有类
*
* @param filePath 文件路径
* 类名集合
* @param childPackage 是否遍历子包
* @return 类的完整名称
* @throws UnsupportedEncodingException
*/
private static List<String> getClassNameByFile(String filePath, boolean childPackage) throws UnsupportedEncodingException {
List<String> myClassName = new ArrayList<>();
// filePath = UrlDecode.getURLDecode(filePath);
File file = new File(filePath);
File[] childFiles = file.listFiles();
if (childFiles == null)
return myClassName;
for (File childFile : childFiles) {
if (childFile.isDirectory()) {
if (childPackage) {
myClassName.addAll(getClassNameByFile(childFile.getPath(), childPackage));
}
} else {
String childFilePath = childFile.getPath();
// childFilePath = FileUtil.clearPath(childFilePath);
if (childFilePath.endsWith(".class")) {
//TODO 这块用com来截取包名有点Low,需要优化
childFilePath = childFilePath.substring(childFilePath.indexOf("com" + File.separatorChar), childFilePath.lastIndexOf("."));
childFilePath = childFilePath.replace(File.separatorChar + "", ".");
myClassName.add(childFilePath);
}
}
}
return myClassName;
}
/**
* 从jar获取某包下所有类
*
* @param jarPath jar文件路径
* @param childPackage 是否遍历子包
* @return 类的完整名称
* @throws UnsupportedEncodingException
*/
private static List<String> getClassNameByJar(String jarPath, boolean childPackage) throws UnsupportedEncodingException {
List<String> myClassName = new ArrayList<String>();
String[] jarInfo = jarPath.split("!");
String jarFilePath = jarInfo[0].substring(jarInfo[0].indexOf("/"));
// jarFilePath = UrlDecode.getURLDecode(jarFilePath);
String packagePath = jarInfo[1].substring(1);
try {
JarFile jarFile = new JarFile(jarFilePath);
Enumeration<JarEntry> entrys = jarFile.entries();
while (entrys.hasMoreElements()) {
JarEntry jarEntry = entrys.nextElement();
String entryName = jarEntry.getName();
if (entryName.endsWith(".class")) {
if (childPackage) {
if (entryName.startsWith(packagePath)) {
entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
myClassName.add(entryName);
}
} else {
int index = entryName.lastIndexOf("/");
String myPackagePath;
if (index != -1) {
myPackagePath = entryName.substring(0, index);
} else {
myPackagePath = entryName;
}
if (myPackagePath.equals(packagePath)) {
entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
myClassName.add(entryName);
}
}
}
}
} catch (Exception e) {
//SystemLog.Log(LogType.systemInfo, e.getMessage(), e);
}
return myClassName;
}
/**
* 从所有jar中搜索该包,并获取该包下所有类
*
* @param urls URL集合
* @param packagePath 包路径
* @param childPackage 是否遍历子包
* @return 类的完整名称
* @throws UnsupportedEncodingException
*/
private static List<String> getClassNameByJars(URL[] urls, String packagePath, boolean childPackage) throws UnsupportedEncodingException {
List<String> myClassName = new ArrayList<String>();
if (urls != null) {
for (int i = 0; i < urls.length; i++) {
URL url = urls[i];
String urlPath = url.getPath();
// 不必搜索classes文件夹
if (urlPath.endsWith("classes/")) {
continue;
}
String jarPath = urlPath + "!/" + packagePath;
myClassName.addAll(getClassNameByJar(jarPath, childPackage));
}
}
return myClassName;
}
}