环境
springboot2.6.6,mybatis-plus3.5.1
@Autowired
SqlSessionFactory factory;
@Autowired
SpringContextUtils springContextUtils;
ConfigurableApplicationContext application = (ConfigurableApplicationContext) SpringContextUtils.getApplicationContext();
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)application.getBeanFactory();
ClassLoader beanClassLoader = beanFactory.getBeanClassLoader();
List<Class<?>> list = RegisterApplication.loadClass("D:\111\2", beanClassLoader);
List<Resource> resourceList = RegisterApplication.loadResource("D:\111\2", beanClassLoader);
Configuration targetConfiguration = factory.getConfiguration();
//先加载jar包里的xml文件,这一步必须在前面
for (Resource mapperLocation : resourceList) {
if (mapperLocation == null) {
continue;
}
try {
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
xmlMapperBuilder.parse();
} catch (Exception e) {
throw new JeecgBootException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
}
}
for(Class<?> clazz : list){
if(!clazz.isInterface()){
Component c = clazz.getAnnotation(Component.class);
String beanName = null;
if(c != null){
beanName = c.value();
}else{
Service s = clazz.getAnnotation(Service.class);
if(s != null){
beanName = s.value();
}
}
if(beanName != null){
//注册bean
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
if(!beanFactory.isBeanNameInUse(beanName)){
beanFactory.registerBeanDefinition(beanName,builder.getRawBeanDefinition());
}
}
}else{
Mapper r = clazz.getAnnotation(Mapper.class);
if(r != null){
//加载mybatisPlus缓存,这一步必须在加载xml之后
String resource = clazz.getName().replace(StringPool.DOT, StringPool.SLASH) + ".java (best guess)";
MapperBuilderAssistant assistant = new MapperBuilderAssistant(targetConfiguration, resource);
GlobalConfigUtils.getSqlInjector(targetConfiguration).inspectInject(assistant, clazz);
}
}
}
//扫描mapper,并注册成bean
try{
Object obj = SpringContextUtils.getBean(MapperScannerConfigurer.class);
MapperScannerConfigurer mapperScanner = (MapperScannerConfigurer) obj;
mapperScanner.setProcessPropertyPlaceHolders(false);
mapperScanner.setBasePackage("com.antjet.**.mapper*");
mapperScanner.postProcessBeanDefinitionRegistry(beanFactory);
mapperScanner.setProcessPropertyPlaceHolders(true);
}catch (NoSuchBeanDefinitionException e){
log.error("未获取到MapperScannerConfigurer");
}
AbstractNodeEvent fybzdEvent = (AbstractNodeEvent)SpringContextUtils.getBean("fybzdEvent");
System.out.println(fybzdEvent.verifyPass("f55b1682f833449393c07b4f2589653f"));
下面是工具类
package org.jeecg.modules.util;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class RegisterApplication {
/**
* 从本地磁盘的某个路径上加载类, 如果是class文件:
* filePath路径应该为class文件包名的上一级,如D:\workspace\classes\com\test\helloworld.class,那么filePath则应该是D:\workspace\classes
* 如果是jar包:
* 则是jar包所在目录,如D:\workspace\classes\helloword.jar,那么filePath则应该为D:\workspace\classes
*
*/
public static List<Class<?>> loadClass(String filePath, ClassLoader beanClassLoader) {
List<Class<?>> classList = new ArrayList<>();
File file = new File(filePath);
if (file.exists() && file.isDirectory()) {
Stack<File> stack = new Stack<>();
stack.push(file);
while (!stack.isEmpty()) {
File path = stack.pop();
// 只需要jar包
File[] classFiles = path.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory() || pathname.getName().endsWith(".jar");
}
});
for (File subFile : classFiles) {
if (subFile.isDirectory()) {
// 如果是目录,则加入栈中
stack.push(subFile);
} else {
URL url = null;
JarFile jar = null;
Method method = null;
Boolean accessible = null;
String className = subFile.getAbsolutePath();
try {
// 反射并调用URLClassLoader的addURL方法
URLClassLoader classLoader = (URLClassLoader) beanClassLoader;
method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
accessible = method.isAccessible();
if (accessible == false) {
method.setAccessible(true);
}
//加载jar包
url = subFile.toURI().toURL();
method.invoke(classLoader, url);
// 获取jar
jar = new JarFile(new File(className));
// 从此jar包 得到一个枚举类
Enumeration<JarEntry> entries = jar.entries();
// 同样的进行循环迭代
while (entries.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/') {
// 获取后面的字符串
name = name.substring(1);
}
name = name.replace(File.separatorChar, '.');
// 获取class文件
if (name.endsWith(".class") && !entry.isDirectory()) {
String className1 = name.substring(0, name.length() - 6);
// 添加到classes
className1 = className1.replace("/", ".");
classList.add(classLoader.loadClass(className1));
}
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
if (null != jar) {
try {
jar.close();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
if (null != method && null != accessible) {
method.setAccessible(accessible);
}
}
}
}
}
}
return classList;
}
public static List<Resource> loadResource(String filePath, ClassLoader beanClassLoader) {
List<Resource> classList = new ArrayList<>();
File file = new File(filePath);
if (file.exists() && file.isDirectory()) {
Stack<File> stack = new Stack<>();
stack.push(file);
while (!stack.isEmpty()) {
File path = stack.pop();
// 只需要class文件或者jar包
File[] classFiles = path.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory() || pathname.getName().endsWith(".jar");
}
});
for (File subFile : classFiles) {
if (subFile.isDirectory()) {
// 如果是目录,则加入栈中
stack.push(subFile);
} else {
URL url = null;
JarFile jar = null;
Method method = null;
Boolean accessible = null;
String className = subFile.getAbsolutePath();
try {
// 反射并调用URLClassLoader的addURL方法
URLClassLoader classLoader = (URLClassLoader) beanClassLoader;
method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
accessible = method.isAccessible();
if (accessible == false) {
method.setAccessible(true);
}
// 如果是jar包,加载该jar包
url = subFile.toURI().toURL();
method.invoke(classLoader, url);
// 获取jar
jar = new JarFile(new File(className));
// 从此jar包 得到一个枚举类
Enumeration<JarEntry> entries = jar.entries();
// 同样的进行循环迭代
while (entries.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/') {
// 获取后面的字符串
name = name.substring(1);
}
// 获取class文件
if (name.endsWith("Mapper.xml")) {
URL uurl = classLoader.findResource(name);
UrlResource resource = new UrlResource(uurl);
classList.add(resource);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != jar) {
try {
jar.close();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
if (null != method && null != accessible) {
method.setAccessible(accessible);
}
}
}
}
}
}
return classList;
}
public static boolean isBean(Class<?> clazz){
Object ann = clazz.getAnnotation(Component.class);
if(ann != null){
return true;
}else{
ann = clazz.getAnnotation(Service.class);
if(ann != null){
return true;
}
}
return false;
}
public static ClassLoader getClassLoader(String url) {
try {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
if (!method.isAccessible()) {
method.setAccessible(true);
}
URLClassLoader classLoader = new URLClassLoader(new URL[]{}, ClassLoader.getSystemClassLoader());
method.invoke(classLoader, new URL(url));
return classLoader;
} catch (Exception e) {
return null;
}
}
}
···