增加Configuration功能

This commit is contained in:
redkale
2024-08-08 16:22:35 +08:00
parent c6fa2a688c
commit cca73a5045
7 changed files with 501 additions and 169 deletions

View File

@@ -5,11 +5,10 @@
*/
package org.redkale.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
/**
* &#64;Resource资源被更新时的监听事件, 本注解只能标记在方法参数为ResourceEvent[]上 <br>
* 注意: 一个类只能存在一个&#64;ResourceChanged的方法 多余的会被忽略 <br>
@@ -29,7 +28,8 @@ import java.lang.annotation.*;
* &#64;ResourceChanged
* private void changeResource(ResourceEvent[] events) {
* for(ResourceEvent event : events) {
* System.out .println("@Resource = " + event.name() + " 资源变更: newVal = " + event.newValue() + ", oldVal = " + event.oldValue());
* System.out .println("@Resource = " + event.name()
* + " 资源变更: newVal = " + event.newValue() + ", oldVal = " + event.oldValue());
* }
* }
*
@@ -56,8 +56,9 @@ import java.lang.annotation.*;
public @interface ResourceChanged {
/**
* 新旧值是否不同时才回调方法 <br>
* true: 新值与旧值不同才回调ResourceChanged方法 false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法
* 新旧值是否不相同的情况下才回调方法 <br>
* true: 新值与旧值不同才回调ResourceChanged方法 <br>
* false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法
*
* @since 2.7.0
* @return boolean

View File

@@ -5,11 +5,10 @@
*/
package org.redkale.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
/**
* &#64;Resource资源被依赖注入时的监听事件。<br>
* 本注解只能标记在空参数或者(String、Object、java.lang.reflect.Field)三个参数类型的任意组合方法上 <br>
@@ -27,8 +26,8 @@ import java.lang.annotation.*;
* private String name;
*
* &#64;ResourceInjected
* private void onInjected(Object src, String fieldName) {
* System.out .println("资源被注入到对象(" + src + ")的字段(" + fieldName + ")上");
* private void onInjected(Object dest, String fieldName) {
* System.out .println("资源被注入到对象(" + dest + ")的字段(" + fieldName + ")上");
* }
* }
*

View File

@@ -33,6 +33,7 @@ import org.redkale.convert.Convert;
import org.redkale.convert.bson.BsonFactory;
import org.redkale.convert.json.*;
import org.redkale.convert.proto.ProtobufFactory;
import org.redkale.inject.Configuration;
import org.redkale.inject.ResourceEvent;
import org.redkale.inject.ResourceFactory;
import org.redkale.inject.ResourceTypeLoader;
@@ -370,8 +371,8 @@ public final class Application {
}
public void init() throws Exception {
// 注册ResourceType
this.initResourceTypeLoader();
// 注册Resource加载器
this.initInjectResource();
// 读取远程配置并合并app.config
this.propertiesModule.initRemoteProperties();
// 解析配置
@@ -388,7 +389,7 @@ public final class Application {
this.onAppPostInit();
}
private void initResourceTypeLoader() {
private void initInjectResource() {
final Application application = this;
// 只有WatchService才能加载Application、WatchFactory
this.resourceFactory.register(new ResourceTypeLoader() {
@@ -700,6 +701,13 @@ public final class Application {
return HttpRpcClient.class;
}
});
// 加载Configuration
ClassFilter<Configuration> filter = new ClassFilter(this.getClassLoader(), Configuration.class);
try {
loadClassByFilters(filter);
} catch (IOException e) {
throw new RedkaleException(e);
}
}
private void registerResourceEnvs(boolean first, Properties... envs) {
@@ -731,7 +739,11 @@ public final class Application {
AutoLoad auto = en.getType().getAnnotation(AutoLoad.class);
if (auto == null || auto.value()) {
int c = RetCodes.load(en.getType());
sb.append("Load RetCodes (type=").append(en.getType().getName() + ") " + c + " records\r\n");
sb.append("Load RetCodes (type=")
.append(en.getType().getName())
.append(") ")
.append(c)
.append(" records\r\n");
}
}
});
@@ -1435,9 +1447,7 @@ public final class Application {
this.onAppPreShutdown();
stopServers();
this.propertiesModule.destroy();
if (this.workExecutor != null) {
this.workExecutor.shutdownNow();
}
this.workExecutor.shutdownNow();
if (this.clientAsyncGroup != null) {
long s = System.currentTimeMillis();
this.clientAsyncGroup.dispose();

View File

@@ -131,7 +131,7 @@ class NodeWebSocketNodeLoader implements ResourceTypeLoader {
continue;
}
sncpResFactory = ns.resourceFactory;
loader = sncpResFactory.findTypeLoader(WebSocketNode.class, field);
loader = sncpResFactory.findResourceTypeLoader(WebSocketNode.class, field);
if (loader != null) {
break;
}

View File

@@ -0,0 +1,15 @@
/*
*/
package org.redkale.inject;
/**
* 启动服务时的初始化配置,需要结合{@link org.redkale.annotation.Resource}使用
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @since 2.8.0
*/
public interface Configuration {}

View File

@@ -18,6 +18,7 @@ import java.util.logging.*;
import org.redkale.annotation.*;
import org.redkale.convert.*;
import org.redkale.convert.json.JsonConvert;
import org.redkale.util.Creator;
import org.redkale.util.RedkaleClassLoader;
import org.redkale.util.RedkaleException;
import org.redkale.util.TypeToken;
@@ -54,12 +55,16 @@ public final class ResourceFactory {
private final List<WeakReference<ResourceFactory>> chidren = new CopyOnWriteArrayList<>();
private final ConcurrentHashMap<Type, ResourceTypeLoader> resTypeLoaderMap = new ConcurrentHashMap();
private final ConcurrentHashMap<Class<? extends Annotation>, ResourceAnnotationLoader> resAnnotationLoaderMap =
new ConcurrentHashMap();
private final ConcurrentHashMap<Type, ResourceTypeLoader> resTypeLoaderMap = new ConcurrentHashMap();
private final ConcurrentHashMap<Type, ConcurrentHashMap<String, Supplier>> resConfigureSupplierMap =
new ConcurrentHashMap();
private final ConcurrentHashMap<Type, ConcurrentHashMap<String, ResourceEntry>> store = new ConcurrentHashMap();
private final ConcurrentHashMap<Type, ConcurrentHashMap<String, ResourceEntry>> entryStore =
new ConcurrentHashMap();
private ResourceFactory(ResourceFactory parent) {
this.parent = parent;
@@ -101,9 +106,9 @@ public final class ResourceFactory {
return result;
}
/** 清空当前ResourceFactory注入资源 */
/** 清空当前注入资源的缓存 */
public void release() {
this.store.clear();
this.entryStore.clear();
}
/** inject时的锁 */
@@ -155,6 +160,80 @@ public final class ResourceFactory {
return rt2 == null ? clazz : rt2.value();
}
/**
* 替换资源名中含${xxx}或{system.property.xxx}的配置项
*
* @param name 资源名
* @return 不包含配置项的资源名
*/
public static String getResourceName(String name) {
return getResourceName(null, name);
}
/**
* 替换资源名中含${xxx}或{system.property.xxx}的配置项
*
* @param parent 父资源名
* @param name 资源名
* @return 不包含配置项的资源名
*/
public static String getResourceName(String parent, String name) {
if (name == null) {
return null;
}
if (name.startsWith("${")) {
String subName = name.substring(2);
int pos = subName.lastIndexOf('}');
if (pos > 0) {
subName = subName.substring(0, pos);
pos = subName.indexOf(':');
if (pos > 0) {
subName = subName.substring(0, pos);
}
name = subName;
}
}
int pos = name.indexOf("{system.property.");
if (pos < 0) {
return (name.contains(Resource.PARENT_NAME) && parent != null)
? name.replace(Resource.PARENT_NAME, parent)
: name;
}
String prefix = name.substring(0, pos);
String subName = name.substring(pos + "{system.property.".length());
pos = subName.lastIndexOf('}');
if (pos < 0) {
return (name.contains(Resource.PARENT_NAME) && parent != null)
? name.replace(Resource.PARENT_NAME, parent)
: name;
}
String postfix = subName.substring(pos + 1);
String property = subName.substring(0, pos);
return getResourceName(parent, prefix + System.getProperty(property, "") + postfix);
}
/**
* 替换资源名中的配置项, 没有配置项返回null
* @param parent 父资源名
* @param name 可能包含配置项的资源名
* @return 替换资源名中的配置项后的资源名
*/
private static String getResourceDefaultValue(String parent, String name) {
if (name.startsWith("${")) {
String subName = name.substring(2);
int pos = subName.lastIndexOf('}');
if (pos > 0) {
subName = subName.substring(0, pos);
pos = subName.indexOf(':');
if (pos > 0) {
String val = subName.substring(pos + 1);
return "null".equals(val) ? null : val;
}
}
}
return null;
}
/**
* 将对象指定类型且name=""注入到资源池中,并同步已被注入的资源
*
@@ -520,6 +599,84 @@ public final class ResourceFactory {
}
}
/**
* 注册 ResourceAnnotationLoader
*
* @param <T> 注解泛型
* @param loader ResourceAnnotationLoader
*/
public <T extends Annotation> void register(final ResourceAnnotationLoader<T> loader) {
Objects.requireNonNull(loader);
parentRoot().resAnnotationLoaderMap.put(loader.annotationType(), loader);
}
/**
* 注册 ResourceTypeLoader
*
* @param loader ResourceTypeLoader
*/
public void register(final ResourceTypeLoader loader) {
resTypeLoaderMap.put(loader.resourceType(), loader);
}
/**
* 注册 Configuration子类
*
* @param <T> 泛型
* @param configuareClass Configuration的实现类
*
*/
public <T extends Configuration> void register(final Class<T> configuareClass) {
Configuration instance = Creator.create(configuareClass).create();
for (Method method : configuareClass.getDeclaredMethods()) {
Resource res = method.getAnnotation(Resource.class);
if (res == null) {
continue;
}
Parameter[] params = method.getParameters();
Supplier[] paramSuppliers = new Supplier[params.length];
for (int i = 0; i < params.length; i++) {
Resource pres = params[i].getAnnotation(Resource.class);
String presName = pres == null ? "" : getResourceName(pres.name());
Type presType0 = params[i].getParameterizedType();
if (presType0 == null) {
presType0 = params[i].getType();
}
Type presType = presType0;
paramSuppliers[i] = () -> load(presName, presType);
}
String resName = getResourceName(res.name());
Type resType = method.getGenericReturnType();
method.setAccessible(true);
Supplier resSupplier = () -> {
Object[] args = new Object[paramSuppliers.length];
for (int i = 0; i < paramSuppliers.length; i++) {
args[i] = paramSuppliers[i].get();
}
try {
return method.invoke(instance, args);
} catch (Exception e) {
throw new RedkaleException(method + " invoke error", e);
}
};
RedkaleClassLoader.putReflectionMethod(configuareClass.getName(), method);
resConfigureSupplierMap
.computeIfAbsent(resType, k -> new ConcurrentHashMap<>())
.put(resName, resSupplier);
}
}
/**
* 将对象以指定资源名和类型注入到资源池中
*
* @param <A> 泛型
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param clazz 资源类型
* @param val 资源对象
* @param wrappers 资源对象的缓存集合
* @return 旧资源对象
*/
private <A> A register(
final boolean autoSync,
final String name,
@@ -593,7 +750,8 @@ public final class ResourceFactory {
}
} while ((c = c.getSuperclass()) != Object.class);
}
ConcurrentHashMap<String, ResourceEntry> map = this.store.computeIfAbsent(clazz, k -> new ConcurrentHashMap());
ConcurrentHashMap<String, ResourceEntry> map =
this.entryStore.computeIfAbsent(clazz, k -> new ConcurrentHashMap());
ResourceEntry re = map.get(name);
if (re == null) {
map.put(name, new ResourceEntry(name, val));
@@ -613,7 +771,7 @@ public final class ResourceFactory {
* @return 是否存在
*/
public <A> boolean contains(boolean recursive, String name, Class<? extends A> clazz) {
Map<String, ResourceEntry> map = this.store.get(clazz);
Map<String, ResourceEntry> map = this.entryStore.get(clazz);
if (map != null) {
return map.containsKey(name);
}
@@ -628,7 +786,7 @@ public final class ResourceFactory {
* @return ResourceFactory
*/
public ResourceFactory findResourceFactory(String name, Type clazz) {
Map<String, ResourceEntry> map = this.store.get(clazz);
Map<String, ResourceEntry> map = this.entryStore.get(clazz);
if (map != null && map.containsKey(name)) {
return this;
}
@@ -638,6 +796,78 @@ public final class ResourceFactory {
return null;
}
/**
* 获取类型对应的ResourceTypeLoader <br>
*
* @param clazz 类型
* @return ResourceTypeLoader
*/
public ResourceTypeLoader findResourceTypeLoader(Type clazz) {
ResourceTypeLoader it = this.resTypeLoaderMap.get(clazz);
if (it != null) {
return it;
}
return parent == null ? null : parent.findResourceTypeLoader(clazz);
}
/**
* 获取类型对应的ResourceTypeLoader <br>
* 优先匹配Type 再匹配Class再匹配父类
* @param ft 类型
* @param field 字段
* @return ResourceTypeLoader
*/
public ResourceTypeLoader findResourceTypeLoader(Type ft, @Nullable Field field) {
ResourceTypeLoader it = this.findClassTypeLoader(ft, field);
if (it == null && field == null && !(ft instanceof Class)) {
return findClassTypeLoader(TypeToken.typeToClass(ft), field);
}
return it == null ? findSuperTypeLoader(ft, field) : it;
}
/**
* 获取类型对应的ResourceTypeLoader <br>
* 优先匹配Type 再匹配Class
* @param ft 类型
* @param field 字段
* @return ResourceTypeLoader
*/
private ResourceTypeLoader findClassTypeLoader(Type ft, @Nullable Field field) {
ResourceTypeLoader it = this.resTypeLoaderMap.get(ft);
if (it == null && field != null) {
it = this.resTypeLoaderMap.get(field.getType());
}
if (it != null) {
return it;
}
return parent == null ? null : parent.findClassTypeLoader(ft, field);
}
/**
* 获取类型对应的ResourceTypeLoader <br>
* 优先匹配Type再匹配父类
*
* @param ft
* @param field
* @return
*/
private ResourceTypeLoader findSuperTypeLoader(Type ft, @Nullable Field field) {
if (field == null) {
return null;
}
Class c = field.getType();
for (Map.Entry<Type, ResourceTypeLoader> en : this.resTypeLoaderMap.entrySet()) {
Type t = en.getKey();
if (t == ft) {
return en.getValue();
}
if (t instanceof Class && ((Class) t).isAssignableFrom(c)) {
return en.getValue();
}
}
return parent == null ? null : parent.findSuperTypeLoader(ft, field);
}
public <A> A find(Class<? extends A> clazz) {
return find("", clazz);
}
@@ -657,7 +887,7 @@ public final class ResourceFactory {
if (rs != null) {
return rs;
}
for (Map.Entry<Type, ConcurrentHashMap<String, ResourceEntry>> en : this.store.entrySet()) {
for (Map.Entry<Type, ConcurrentHashMap<String, ResourceEntry>> en : this.entryStore.entrySet()) {
if (!(en.getKey() instanceof Class)) {
continue;
}
@@ -672,8 +902,8 @@ public final class ResourceFactory {
return null;
}
private ResourceEntry findEntry(String name, Type clazz) {
Map<String, ResourceEntry> map = this.store.get(clazz);
private <A> ResourceEntry<A> findEntry(String name, Type clazz) {
Map<String, ResourceEntry> map = this.entryStore.get(clazz);
if (map != null) {
ResourceEntry re = map.get(name);
if (re != null) {
@@ -686,27 +916,44 @@ public final class ResourceFactory {
return null;
}
public <A> A load(Class<? extends A> clazz) {
/**
* 加载资源对象, 没有返回null
*
* @param <A> 泛型
* @param clazz 资源类型
* @return 资源对象
*
* @since 2.8.0
*/
public <A> A load(Type clazz) {
return load("", clazz);
}
/**
* 加载资源对象, 没有返回null
*
* @param <A> 泛型
* @param name 资源名
* @param clazz 资源类型
* @return 资源对象
*
* @since 2.8.0
*/
public <A> A load(String name, Type clazz) {
A val = find(name, clazz);
if (val == null) {
ResourceTypeLoader loader = findResourceTypeLoader(clazz);
if (loader != null) {
val = (A) loader.load(this, null, null, name, null, null);
}
}
return val;
}
public <A> A load(String name, Class<? extends A> clazz) {
A val = find(name, clazz);
if (val == null) {
ResourceTypeLoader loader = findResourceTypeLoader(clazz);
if (loader != null) {
val = (A) loader.load(this, null, null, name, null, null);
Map<String, Supplier> supplierMap = this.resConfigureSupplierMap.get(clazz);
Supplier supplier = supplierMap == null ? null : supplierMap.get(name);
if (supplier != null) {
val = (A) supplier.get();
if (val != null) {
inject(name, val);
}
} else {
ResourceTypeLoader loader = findResourceTypeLoader(clazz, (Field) null);
if (loader != null) {
val = (A) loader.load(this, null, null, name, null, null);
}
}
}
return val;
@@ -721,7 +968,7 @@ public final class ResourceFactory {
}
private <A> List<A> query(final List<A> list, Type clazz) {
Map<String, ResourceEntry> map = this.store.get(clazz);
Map<String, ResourceEntry> map = this.entryStore.get(clazz);
if (map != null) {
for (ResourceEntry re : map.values()) {
if (re.value != null) {
@@ -743,7 +990,7 @@ public final class ResourceFactory {
if (predicate == null) {
return list;
}
for (ConcurrentHashMap<String, ResourceEntry> map : this.store.values()) {
for (ConcurrentHashMap<String, ResourceEntry> map : this.entryStore.values()) {
for (Map.Entry<String, ResourceEntry> en : map.entrySet()) {
if (predicate.test(en.getKey(), en.getValue().value)) {
list.add((A) en.getValue().value);
@@ -756,48 +1003,98 @@ public final class ResourceFactory {
return list;
}
private <A> ResourceEntry<A> findEntry(String name, Class<? extends A> clazz) {
Map<String, ResourceEntry> map = this.store.get(clazz);
if (map != null) {
ResourceEntry rs = map.get(name);
if (rs != null) {
return rs;
}
}
if (parent != null) {
return parent.findEntry(name, clazz);
}
return null;
}
/**
* 注入资源对象
*
* @param srcObj 资源依附对象
* @return 是否成功注入
*/
public boolean inject(final Object srcObj) {
return inject(srcObj, null);
}
/**
* 注入资源对象
*
* @param <T> 泛型
* @param srcObj 资源依附对象
* @param attachment 附加对象
* @return 是否成功注入
*/
public <T> boolean inject(final Object srcObj, final T attachment) {
return inject(srcObj, attachment, null);
}
/**
* 注入资源对象
*
* @param srcObj 资源依附对象
* @param consumer 字段处理函数
* @return 是否成功注入
*/
public boolean inject(final Object srcObj, final BiConsumer<Object, Field> consumer) {
return inject(srcObj, null, consumer);
}
/**
* 注入资源对象
*
* @param <T> 泛型
* @param srcObj 资源依附对象
* @param attachment 附加对象
* @param consumer 字段处理函数
* @return 是否成功注入
*/
public <T> boolean inject(final Object srcObj, final T attachment, final BiConsumer<Object, Field> consumer) {
return inject(null, srcObj, attachment, consumer, new ArrayList());
}
/**
* 注入资源对象
*
* @param srcResourceName 资源名
* @param srcObj 资源依附对象
* @return 是否成功注入
*/
public boolean inject(final String srcResourceName, final Object srcObj) {
return inject(srcResourceName, srcObj, null);
}
/**
* 注入资源对象
*
* @param <T> 泛型
* @param srcResourceName 资源名
* @param srcObj 资源依附对象
* @param attachment 附加对象
* @return 是否成功注入
*/
public <T> boolean inject(final String srcResourceName, final Object srcObj, final T attachment) {
return inject(srcResourceName, srcObj, attachment, null);
}
/**
* 注入资源对象
*
* @param srcResourceName 资源名
* @param srcObj 资源依附对象
* @param consumer 字段处理函数
* @return 是否成功注入
*/
public boolean inject(final String srcResourceName, final Object srcObj, final BiConsumer<Object, Field> consumer) {
return inject(srcResourceName, srcObj, null, consumer);
}
/**
* 注入资源对象
*
* @param <T> 泛型
* @param srcResourceName 资源名
* @param srcObj 资源依附对象
* @param attachment 附加对象
* @param consumer 字段处理函数
* @return 是否成功注入
*/
public <T> boolean inject(
final String srcResourceName,
final Object srcObj,
@@ -806,61 +1103,17 @@ public final class ResourceFactory {
return inject(srcResourceName, srcObj, attachment, consumer, new ArrayList());
}
public static String getResourceName(String name) {
return getResourceName(null, name);
}
public static String getResourceName(String parent, String name) {
if (name == null) {
return null;
}
if (name.startsWith("${")) {
String subName = name.substring(2);
int pos = subName.lastIndexOf('}');
if (pos > 0) {
subName = subName.substring(0, pos);
pos = subName.indexOf(':');
if (pos > 0) {
subName = subName.substring(0, pos);
}
name = subName;
}
}
int pos = name.indexOf("{system.property.");
if (pos < 0) {
return (name.contains(Resource.PARENT_NAME) && parent != null)
? name.replace(Resource.PARENT_NAME, parent)
: name;
}
String prefix = name.substring(0, pos);
String subName = name.substring(pos + "{system.property.".length());
pos = subName.lastIndexOf('}');
if (pos < 0) {
return (name.contains(Resource.PARENT_NAME) && parent != null)
? name.replace(Resource.PARENT_NAME, parent)
: name;
}
String postfix = subName.substring(pos + 1);
String property = subName.substring(0, pos);
return getResourceName(parent, prefix + System.getProperty(property, "") + postfix);
}
private static String getResourceDefaultValue(String parent, String name) {
if (name.startsWith("${")) {
String subName = name.substring(2);
int pos = subName.lastIndexOf('}');
if (pos > 0) {
subName = subName.substring(0, pos);
pos = subName.indexOf(':');
if (pos > 0) {
String val = subName.substring(pos + 1);
return "null".equals(val) ? null : val;
}
}
}
return null;
}
/**
* 注入资源对象
*
* @param <T> 泛型
* @param srcResourceName 资源名
* @param srcObj 资源依附对象
* @param attachment 附加对象
* @param consumer 字段处理函数
* @param list 层级对象集合
* @return 是否成功注入
*/
private <T> boolean inject(
String srcResourceName,
Object srcObj,
@@ -1017,17 +1270,19 @@ public final class ResourceFactory {
&& rcname.startsWith("property.")) { // 兼容2.8.0之前版本自动追加property.开头的配置项
re = findEntry(rcname.substring("property.".length()), String.class);
} else {
re = findEntry(rcname, classType);
rs = findEntry(rcname, classType);
}
}
if (re == null) {
ResourceTypeLoader it = findTypeLoader(gencType, field);
ResourceTypeLoader it = findResourceTypeLoader(gencType, field);
if (it != null) {
rs = it.load(this, srcResourceName, srcObj, rcname, field, attachment);
autoRegNull = it.autoNone();
if (rs == null) {
re = findEntry(rcname, gencType);
}
} else {
rs = load(rcname, gencType);
}
}
if (rs == null && re == null && gencType != classType) {
@@ -1049,17 +1304,19 @@ public final class ResourceFactory {
}
}
if (re == null) {
ResourceTypeLoader it = findTypeLoader(classType, field);
ResourceTypeLoader it = findResourceTypeLoader(classType, field);
if (it != null) {
rs = it.load(this, srcResourceName, srcObj, rcname, field, attachment);
autoRegNull = it.autoNone();
if (rs == null) {
re = findEntry(rcname, classType);
}
} else {
re = load(rcname, gencType);
}
}
}
if (rs == null && re == null && autoRegNull && rcname.indexOf(Resource.PARENT_NAME) < 0) {
if (rs == null && re == null && autoRegNull && !rcname.contains(Resource.PARENT_NAME)) {
if (rcname.startsWith("${")) {
String sub = rcname.substring(rcname.lastIndexOf("${") + 2, rcname.lastIndexOf('}'));
register(sub, gencType, null); // 自动注入null的值
@@ -1106,28 +1363,11 @@ public final class ResourceFactory {
}
}
public <T extends Annotation> void register(final ResourceAnnotationLoader<T> loader) {
Objects.requireNonNull(loader);
parentRoot().resAnnotationLoaderMap.put(loader.annotationType(), loader);
}
public void register(final ResourceTypeLoader rs) {
resTypeLoaderMap.put(rs.resourceType(), rs);
}
public ResourceTypeLoader findResourceTypeLoader(Type clazz) {
ResourceTypeLoader it = this.resTypeLoaderMap.get(clazz);
if (it != null) {
return it;
}
return parent == null ? null : parent.findResourceTypeLoader(clazz);
}
public ResourceTypeLoader findTypeLoader(Type ft, @Nullable Field field) {
ResourceTypeLoader it = this.findMatchTypeLoader(ft, field);
return it == null ? findRegexTypeLoader(ft, field) : it;
}
/**
* 获取最底层ResourceFactory
*
* @return ResourceFactory
*/
private ResourceFactory parentRoot() {
if (parent == null) {
return this;
@@ -1135,35 +1375,14 @@ public final class ResourceFactory {
return parent.parentRoot();
}
private ResourceTypeLoader findMatchTypeLoader(Type ft, @Nullable Field field) {
ResourceTypeLoader it = this.resTypeLoaderMap.get(ft);
if (it == null && field != null) {
it = this.resTypeLoaderMap.get(field.getType());
}
if (it != null) {
return it;
}
return parent == null ? null : parent.findMatchTypeLoader(ft, field);
}
private ResourceTypeLoader findRegexTypeLoader(Type ft, @Nullable Field field) {
if (field == null) {
return null;
}
Class c = field.getType();
for (Map.Entry<Type, ResourceTypeLoader> en : this.resTypeLoaderMap.entrySet()) {
Type t = en.getKey();
if (t == ft) {
return en.getValue();
}
if (t instanceof Class && ((Class) t).isAssignableFrom(c)) {
return en.getValue();
}
}
return parent == null ? null : parent.findRegexTypeLoader(ft, field);
}
private void onResourceInjected(Object src, Field field, Object res) {
/**
* 调用标记ResourceInjected的监听方法
*
* @param dest 资源的依附对象
* @param field 资源的依附对象的字段
* @param res 资源对象
*/
private void onResourceInjected(Object dest, Field field, Object res) {
if (res == null
|| res.getClass().isPrimitive()
|| res.getClass().getName().startsWith("java.")
@@ -1179,7 +1398,7 @@ public final class ResourceFactory {
Object[] params = new Object[paramTypes.length];
for (int i = 0; i < params.length; i++) {
if (paramTypes[i] == Object.class) {
params[i] = src;
params[i] = dest;
} else if (paramTypes[i] == String.class) {
params[i] = field.getName();
} else if (paramTypes[i] == Field.class) {
@@ -1200,6 +1419,11 @@ public final class ResourceFactory {
}
}
/**
* 资源依附信息的缓存对象
*
* @param <T> 泛型
*/
private static class ResourceEntry<T> {
public final String name;
@@ -1267,6 +1491,11 @@ public final class ResourceFactory {
}
}
/**
* 资源字段和变更监听方法信息的缓存对象
*
* @param <T> 泛型
*/
private static class ResourceElement<T> {
private static final ReentrantLock syncLock = new ReentrantLock();

View File

@@ -0,0 +1,78 @@
/*
*/
package org.redkale.test.inject;
import org.junit.jupiter.api.*;
import org.redkale.annotation.Resource;
import org.redkale.convert.json.JsonFactory;
import org.redkale.inject.Configuration;
import org.redkale.inject.ResourceFactory;
/**
*
* @author zhangjx
*/
public class ConfigurationTest {
public static void main(String[] args) throws Throwable {
ConfigurationTest test = new ConfigurationTest();
test.run();
}
@Test
public void run() throws Exception {
ResourceFactory factory = ResourceFactory.create();
factory.register("a.id", 1234);
factory.register("a.name", "my a name");
factory.register("b.id", 4321);
factory.register("b.name", "my b name");
factory.register(DiyConfiguration.class);
BeanB pb = new BeanB();
factory.inject(pb);
Assertions.assertEquals(new BeanA(1234, "my a name", "auto").toString(), pb.bean.toString());
System.out.println(pb.bean);
}
public static class DiyConfiguration implements Configuration {
@Resource(name = "a")
BeanA createBeanA() {
System.out.println("创建一个Bean");
BeanA bean = new BeanA();
bean.desc = "auto";
return bean;
}
}
public static class BeanB {
@Resource(name = "a")
public BeanA bean;
}
public static class BeanA {
@Resource(name = "@.id")
public int id;
@Resource(name = "@.name")
public String name;
public String desc;
public BeanA() {}
public BeanA(int id, String name, String desc) {
this.id = id;
this.name = name;
this.desc = desc;
}
@Override
public String toString() {
return JsonFactory.root().getConvert().convertTo(this);
}
}
}