generated from mingliqiye/lib-tem
All checks were successful
Gitea Actions Build / Build (push) Successful in 51s
- 新增 AesUtils 类,提供 AES/GCM 模式的加密解密方法- 更新 .prettierrc配置,将 useTabs 设置为 true - 重构 Base64Utils 和 Collection 类的代码结构- 简化 ComponentBean 注解定义
249 lines
6.7 KiB
Java
249 lines
6.7 KiB
Java
package com.mingliqiye.utils.bean;
|
||
|
||
import com.mingliqiye.utils.bean.annotation.ComponentBean;
|
||
import com.mingliqiye.utils.bean.annotation.InjectBean;
|
||
import java.io.File;
|
||
import java.lang.reflect.Field;
|
||
import java.net.URL;
|
||
import java.util.Enumeration;
|
||
import java.util.concurrent.ConcurrentHashMap;
|
||
import java.util.concurrent.ConcurrentMap;
|
||
|
||
/**
|
||
* 类似于SpringBoot的Bean管理器
|
||
*
|
||
* @author MingLiPro
|
||
*/
|
||
public class Factory {
|
||
|
||
/**
|
||
* 存储所有已注册的Bean实例,键为Bean名称,值为Bean实例
|
||
*/
|
||
public static final ConcurrentMap<String, Object> beans =
|
||
new ConcurrentHashMap<>();
|
||
|
||
/**
|
||
* 存储按类型查找的Bean实例,键为Bean的Class对象,值为Bean实例
|
||
*/
|
||
private static final ConcurrentMap<Class<?>, Object> typeBeans =
|
||
new ConcurrentHashMap<>();
|
||
|
||
/**
|
||
* 私有构造函数,防止外部实例化该类
|
||
*/
|
||
private Factory() {}
|
||
|
||
/**
|
||
* 自动扫描指定类所在包下的所有类并注册为Bean
|
||
*
|
||
* @param c 指定的类,用于获取其所在的包
|
||
* @throws IllegalArgumentException 如果传入的类为null或位于默认包中
|
||
*/
|
||
public static void autoScan(Class<?> c) {
|
||
if (c == null) {
|
||
throw new IllegalArgumentException("Class cannot be null");
|
||
}
|
||
Package pkg = c.getPackage();
|
||
if (pkg == null) {
|
||
throw new IllegalArgumentException(
|
||
"Class is in the default package"
|
||
);
|
||
}
|
||
scan(pkg.getName());
|
||
}
|
||
|
||
/**
|
||
* 扫描指定包路径下的所有类文件,并注册其中带有@ComponentBean注解的类为Bean
|
||
*
|
||
* @param basePackage 要扫描的基础包名
|
||
* @throws RuntimeException 如果在扫描过程中发生异常
|
||
*/
|
||
public static void scan(String basePackage) {
|
||
try {
|
||
String path = basePackage.replace('.', '/');
|
||
ClassLoader classLoader =
|
||
Thread.currentThread().getContextClassLoader();
|
||
Enumeration<URL> resources = null;
|
||
resources = classLoader.getResources(path);
|
||
while (resources.hasMoreElements()) {
|
||
URL resource = resources.nextElement();
|
||
File file = new File(resource.toURI());
|
||
scanDirectory(file, basePackage);
|
||
}
|
||
injectDependencies();
|
||
} catch (Exception e) {
|
||
throw new RuntimeException(e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 递归扫描目录中的所有类文件,并注册符合条件的类为Bean
|
||
*
|
||
* @param directory 当前要扫描的目录
|
||
* @param packageName 当前目录对应的包名
|
||
* @throws Exception 如果在扫描或类加载过程中发生异常
|
||
*/
|
||
private static void scanDirectory(File directory, String packageName)
|
||
throws Exception {
|
||
File[] files = directory.listFiles();
|
||
if (files == null) {
|
||
return;
|
||
}
|
||
|
||
for (File file : files) {
|
||
if (file.isDirectory()) {
|
||
scanDirectory(file, packageName + "." + file.getName());
|
||
} else if (file.getName().endsWith(".class")) {
|
||
String className =
|
||
packageName + '.' + file.getName().replace(".class", "");
|
||
registerComponent(Class.forName(className));
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 注册一个带有@ComponentBean注解的类为Bean实例
|
||
*
|
||
* @param clazz 要注册的类
|
||
* @throws Exception 如果在实例化类或处理注解时发生异常
|
||
*/
|
||
private static void registerComponent(Class<?> clazz) throws Exception {
|
||
if (clazz.isAnnotationPresent(ComponentBean.class)) {
|
||
ComponentBean component = clazz.getAnnotation(ComponentBean.class);
|
||
String name = component.value().isEmpty()
|
||
? clazz.getName()
|
||
: component.value();
|
||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||
beans.put(name, instance);
|
||
typeBeans.put(clazz, instance);
|
||
|
||
for (Class<?> interfaceClass : clazz.getInterfaces()) {
|
||
typeBeans.putIfAbsent(interfaceClass, instance);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 对所有已注册的Bean进行依赖注入处理
|
||
*
|
||
* @throws Exception 如果在注入过程中发生异常
|
||
*/
|
||
private static void injectDependencies() throws Exception {
|
||
for (Object bean : beans.values()) {
|
||
for (Field field : bean.getClass().getDeclaredFields()) {
|
||
if (field.isAnnotationPresent(InjectBean.class)) {
|
||
InjectBean inject = field.getAnnotation(InjectBean.class);
|
||
Object dependency = findDependency(
|
||
field.getType(),
|
||
inject.value()
|
||
);
|
||
if (dependency == null) {
|
||
throw new IllegalStateException(
|
||
"No suitable dependency found for field " +
|
||
field.getName() +
|
||
" in class " +
|
||
bean.getClass().getName()
|
||
);
|
||
}
|
||
field.setAccessible(true);
|
||
field.set(bean, dependency);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据类型和名称查找对应的依赖实例
|
||
*
|
||
* @param type 依赖的类型
|
||
* @param name 依赖的名称(可为空)
|
||
* @return 找到的依赖实例,未找到则返回null
|
||
*/
|
||
private static Object findDependency(Class<?> type, String name) {
|
||
if (!name.isEmpty()) {
|
||
return beans.get(name);
|
||
}
|
||
|
||
Object dependency = typeBeans.get(type);
|
||
if (dependency != null) {
|
||
return dependency;
|
||
}
|
||
|
||
for (Class<?> interfaceType : typeBeans.keySet()) {
|
||
if (type.isAssignableFrom(interfaceType)) {
|
||
return typeBeans.get(interfaceType);
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 将一个对象添加到Bean容器中,使用其类名作为键
|
||
*
|
||
* @param object 要添加的对象
|
||
* @throws RuntimeException 如果在注入依赖时发生异常
|
||
*/
|
||
public static void add(Object object) {
|
||
Class<?> clazz = object.getClass();
|
||
String name = clazz.getName();
|
||
beans.put(name, object);
|
||
typeBeans.put(clazz, object);
|
||
try {
|
||
injectDependencies();
|
||
} catch (Exception e) {
|
||
throw new RuntimeException(e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 将一个对象以指定名称添加到Bean容器中
|
||
*
|
||
* @param name Bean的名称
|
||
* @param object 要添加的对象
|
||
* @throws RuntimeException 如果在注入依赖时发生异常
|
||
*/
|
||
public static void add(String name, Object object) {
|
||
beans.put(name, object);
|
||
typeBeans.put(object.getClass(), object);
|
||
try {
|
||
injectDependencies();
|
||
} catch (Exception e) {
|
||
throw new RuntimeException(e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据类型获取对应的Bean实例
|
||
*
|
||
* @param objclass Bean的类型
|
||
* @param <T> Bean的泛型类型
|
||
* @return 对应类型的Bean实例,未找到则返回null
|
||
*/
|
||
public static <T> T get(Class<T> objclass) {
|
||
return objclass.cast(typeBeans.get(objclass));
|
||
}
|
||
|
||
/**
|
||
* 根据名称和类型获取对应的Bean实例
|
||
*
|
||
* @param name Bean的名称
|
||
* @param objclass Bean的类型
|
||
* @param <T> Bean的泛型类型
|
||
* @return 对应名称和类型的Bean实例,未找到则返回null
|
||
*/
|
||
public static <T> T get(String name, Class<T> objclass) {
|
||
return objclass.cast(beans.get(name));
|
||
}
|
||
|
||
/**
|
||
* 根据名称获取对应的Bean实例
|
||
*
|
||
* @param name Bean的名称
|
||
* @return 对应名称的Bean实例,未找到则返回null
|
||
*/
|
||
public static Object get(String name) {
|
||
return beans.get(name);
|
||
}
|
||
}
|