From cca73a5045925d6f763a9ff34c7e8654c9bd3aca Mon Sep 17 00:00:00 2001 From: redkale Date: Thu, 8 Aug 2024 16:22:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Configuration=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redkale/annotation/ResourceChanged.java | 11 +- .../redkale/annotation/ResourceInjected.java | 7 +- .../java/org/redkale/boot/Application.java | 24 +- .../redkale/boot/NodeWebSocketNodeLoader.java | 2 +- .../org/redkale/inject/Configuration.java | 15 + .../org/redkale/inject/ResourceFactory.java | 533 +++++++++++++----- .../test/inject/ConfigurationTest.java | 78 +++ 7 files changed, 501 insertions(+), 169 deletions(-) create mode 100644 src/main/java/org/redkale/inject/Configuration.java create mode 100644 src/test/java/org/redkale/test/inject/ConfigurationTest.java diff --git a/src/main/java/org/redkale/annotation/ResourceChanged.java b/src/main/java/org/redkale/annotation/ResourceChanged.java index 9fdcd34b3..82636bf2c 100644 --- a/src/main/java/org/redkale/annotation/ResourceChanged.java +++ b/src/main/java/org/redkale/annotation/ResourceChanged.java @@ -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.*; - /** * @Resource资源被更新时的监听事件, 本注解只能标记在方法参数为ResourceEvent[]上
* 注意: 一个类只能存在一个@ResourceChanged的方法, 多余的会被忽略
@@ -29,7 +28,8 @@ import java.lang.annotation.*; * @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 { /** - * 新旧值是否不同时才回调方法
- * true: 新值与旧值不同时才回调ResourceChanged方法 false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法 + * 新旧值是否不相同的情况下才回调方法
+ * true: 新值与旧值不相同才回调ResourceChanged方法
+ * false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法 * * @since 2.7.0 * @return boolean diff --git a/src/main/java/org/redkale/annotation/ResourceInjected.java b/src/main/java/org/redkale/annotation/ResourceInjected.java index 9c865ad8c..3f7398e91 100644 --- a/src/main/java/org/redkale/annotation/ResourceInjected.java +++ b/src/main/java/org/redkale/annotation/ResourceInjected.java @@ -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.*; - /** * @Resource资源被依赖注入时的监听事件。
* 本注解只能标记在空参数或者(String、Object、java.lang.reflect.Field)三个参数类型的任意组合方法上
@@ -27,8 +26,8 @@ import java.lang.annotation.*; * private String name; * * @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 + ")上"); * } * } * diff --git a/src/main/java/org/redkale/boot/Application.java b/src/main/java/org/redkale/boot/Application.java index 54893f982..cf469edac 100644 --- a/src/main/java/org/redkale/boot/Application.java +++ b/src/main/java/org/redkale/boot/Application.java @@ -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 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(); diff --git a/src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java b/src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java index bb2425e9a..b761d0bc9 100644 --- a/src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java +++ b/src/main/java/org/redkale/boot/NodeWebSocketNodeLoader.java @@ -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; } diff --git a/src/main/java/org/redkale/inject/Configuration.java b/src/main/java/org/redkale/inject/Configuration.java new file mode 100644 index 000000000..c3af0941e --- /dev/null +++ b/src/main/java/org/redkale/inject/Configuration.java @@ -0,0 +1,15 @@ +/* + +*/ + +package org.redkale.inject; + +/** + * 启动服务时的初始化配置,需要结合{@link org.redkale.annotation.Resource}使用 + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * @since 2.8.0 + */ +public interface Configuration {} diff --git a/src/main/java/org/redkale/inject/ResourceFactory.java b/src/main/java/org/redkale/inject/ResourceFactory.java index 11e41e29c..bbe9b2fc6 100644 --- a/src/main/java/org/redkale/inject/ResourceFactory.java +++ b/src/main/java/org/redkale/inject/ResourceFactory.java @@ -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> chidren = new CopyOnWriteArrayList<>(); + private final ConcurrentHashMap resTypeLoaderMap = new ConcurrentHashMap(); + private final ConcurrentHashMap, ResourceAnnotationLoader> resAnnotationLoaderMap = new ConcurrentHashMap(); - private final ConcurrentHashMap resTypeLoaderMap = new ConcurrentHashMap(); + private final ConcurrentHashMap> resConfigureSupplierMap = + new ConcurrentHashMap(); - private final ConcurrentHashMap> store = new ConcurrentHashMap(); + private final ConcurrentHashMap> 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 注解泛型 + * @param loader ResourceAnnotationLoader + */ + public void register(final ResourceAnnotationLoader 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 泛型 + * @param configuareClass Configuration的实现类 + * + */ + public void register(final Class 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 泛型 + * @param autoSync 是否同步已被注入的资源 + * @param name 资源名 + * @param clazz 资源类型 + * @param val 资源对象 + * @param wrappers 资源对象的缓存集合 + * @return 旧资源对象 + */ private A register( final boolean autoSync, final String name, @@ -593,7 +750,8 @@ public final class ResourceFactory { } } while ((c = c.getSuperclass()) != Object.class); } - ConcurrentHashMap map = this.store.computeIfAbsent(clazz, k -> new ConcurrentHashMap()); + ConcurrentHashMap 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 boolean contains(boolean recursive, String name, Class clazz) { - Map map = this.store.get(clazz); + Map 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 map = this.store.get(clazz); + Map map = this.entryStore.get(clazz); if (map != null && map.containsKey(name)) { return this; } @@ -638,6 +796,78 @@ public final class ResourceFactory { return null; } + /** + * 获取类型对应的ResourceTypeLoader
+ * + * @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
+ * 优先匹配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
+ * 优先匹配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
+ * 优先匹配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 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 find(Class clazz) { return find("", clazz); } @@ -657,7 +887,7 @@ public final class ResourceFactory { if (rs != null) { return rs; } - for (Map.Entry> en : this.store.entrySet()) { + for (Map.Entry> 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 map = this.store.get(clazz); + private ResourceEntry findEntry(String name, Type clazz) { + Map 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 load(Class clazz) { + /** + * 加载资源对象, 没有返回null + * + * @param 泛型 + * @param clazz 资源类型 + * @return 资源对象 + * + * @since 2.8.0 + */ + public A load(Type clazz) { return load("", clazz); } + /** + * 加载资源对象, 没有返回null + * + * @param 泛型 + * @param name 资源名 + * @param clazz 资源类型 + * @return 资源对象 + * + * @since 2.8.0 + */ public 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 load(String name, Class 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 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 List query(final List list, Type clazz) { - Map map = this.store.get(clazz); + Map 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 map : this.store.values()) { + for (ConcurrentHashMap map : this.entryStore.values()) { for (Map.Entry 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 ResourceEntry findEntry(String name, Class clazz) { - Map 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 泛型 + * @param srcObj 资源依附对象 + * @param attachment 附加对象 + * @return 是否成功注入 + */ public 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 consumer) { return inject(srcObj, null, consumer); } + /** + * 注入资源对象 + * + * @param 泛型 + * @param srcObj 资源依附对象 + * @param attachment 附加对象 + * @param consumer 字段处理函数 + * @return 是否成功注入 + */ public boolean inject(final Object srcObj, final T attachment, final BiConsumer 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 泛型 + * @param srcResourceName 资源名 + * @param srcObj 资源依附对象 + * @param attachment 附加对象 + * @return 是否成功注入 + */ public 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 consumer) { return inject(srcResourceName, srcObj, null, consumer); } + /** + * 注入资源对象 + * + * @param 泛型 + * @param srcResourceName 资源名 + * @param srcObj 资源依附对象 + * @param attachment 附加对象 + * @param consumer 字段处理函数 + * @return 是否成功注入 + */ public 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 泛型 + * @param srcResourceName 资源名 + * @param srcObj 资源依附对象 + * @param attachment 附加对象 + * @param consumer 字段处理函数 + * @param list 层级对象集合 + * @return 是否成功注入 + */ private 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 void register(final ResourceAnnotationLoader 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 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 泛型 + */ private static class ResourceEntry { public final String name; @@ -1267,6 +1491,11 @@ public final class ResourceFactory { } } + /** + * 资源字段和变更监听方法信息的缓存对象 + * + * @param 泛型 + */ private static class ResourceElement { private static final ReentrantLock syncLock = new ReentrantLock(); diff --git a/src/test/java/org/redkale/test/inject/ConfigurationTest.java b/src/test/java/org/redkale/test/inject/ConfigurationTest.java new file mode 100644 index 000000000..0bd891858 --- /dev/null +++ b/src/test/java/org/redkale/test/inject/ConfigurationTest.java @@ -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); + } + } +}