增加Configuration功能
This commit is contained in:
@@ -5,11 +5,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.annotation;
|
package org.redkale.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
import static java.lang.annotation.ElementType.METHOD;
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Resource资源被更新时的监听事件, 本注解只能标记在方法参数为ResourceEvent[]上 <br>
|
* @Resource资源被更新时的监听事件, 本注解只能标记在方法参数为ResourceEvent[]上 <br>
|
||||||
* 注意: 一个类只能存在一个@ResourceChanged的方法, 多余的会被忽略 <br>
|
* 注意: 一个类只能存在一个@ResourceChanged的方法, 多余的会被忽略 <br>
|
||||||
@@ -29,7 +28,8 @@ import java.lang.annotation.*;
|
|||||||
* @ResourceChanged
|
* @ResourceChanged
|
||||||
* private void changeResource(ResourceEvent[] events) {
|
* private void changeResource(ResourceEvent[] events) {
|
||||||
* for(ResourceEvent event : 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 {
|
public @interface ResourceChanged {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新旧值是否不同时才回调方法 <br>
|
* 新旧值是否不相同的情况下才回调方法 <br>
|
||||||
* true: 新值与旧值不同时才回调ResourceChanged方法 false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法
|
* true: 新值与旧值不相同才回调ResourceChanged方法 <br>
|
||||||
|
* false: 只要执行了ResourceFactory.register 就回调ResourceChanged方法
|
||||||
*
|
*
|
||||||
* @since 2.7.0
|
* @since 2.7.0
|
||||||
* @return boolean
|
* @return boolean
|
||||||
|
|||||||
@@ -5,11 +5,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.annotation;
|
package org.redkale.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
import static java.lang.annotation.ElementType.METHOD;
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Resource资源被依赖注入时的监听事件。<br>
|
* @Resource资源被依赖注入时的监听事件。<br>
|
||||||
* 本注解只能标记在空参数或者(String、Object、java.lang.reflect.Field)三个参数类型的任意组合方法上 <br>
|
* 本注解只能标记在空参数或者(String、Object、java.lang.reflect.Field)三个参数类型的任意组合方法上 <br>
|
||||||
@@ -27,8 +26,8 @@ import java.lang.annotation.*;
|
|||||||
* private String name;
|
* private String name;
|
||||||
*
|
*
|
||||||
* @ResourceInjected
|
* @ResourceInjected
|
||||||
* private void onInjected(Object src, String fieldName) {
|
* private void onInjected(Object dest, String fieldName) {
|
||||||
* System.out .println("资源被注入到对象(" + src + ")的字段(" + fieldName + ")上");
|
* System.out .println("资源被注入到对象(" + dest + ")的字段(" + fieldName + ")上");
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.redkale.convert.Convert;
|
|||||||
import org.redkale.convert.bson.BsonFactory;
|
import org.redkale.convert.bson.BsonFactory;
|
||||||
import org.redkale.convert.json.*;
|
import org.redkale.convert.json.*;
|
||||||
import org.redkale.convert.proto.ProtobufFactory;
|
import org.redkale.convert.proto.ProtobufFactory;
|
||||||
|
import org.redkale.inject.Configuration;
|
||||||
import org.redkale.inject.ResourceEvent;
|
import org.redkale.inject.ResourceEvent;
|
||||||
import org.redkale.inject.ResourceFactory;
|
import org.redkale.inject.ResourceFactory;
|
||||||
import org.redkale.inject.ResourceTypeLoader;
|
import org.redkale.inject.ResourceTypeLoader;
|
||||||
@@ -370,8 +371,8 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
// 注册ResourceType
|
// 注册Resource加载器
|
||||||
this.initResourceTypeLoader();
|
this.initInjectResource();
|
||||||
// 读取远程配置,并合并app.config
|
// 读取远程配置,并合并app.config
|
||||||
this.propertiesModule.initRemoteProperties();
|
this.propertiesModule.initRemoteProperties();
|
||||||
// 解析配置
|
// 解析配置
|
||||||
@@ -388,7 +389,7 @@ public final class Application {
|
|||||||
this.onAppPostInit();
|
this.onAppPostInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initResourceTypeLoader() {
|
private void initInjectResource() {
|
||||||
final Application application = this;
|
final Application application = this;
|
||||||
// 只有WatchService才能加载Application、WatchFactory
|
// 只有WatchService才能加载Application、WatchFactory
|
||||||
this.resourceFactory.register(new ResourceTypeLoader() {
|
this.resourceFactory.register(new ResourceTypeLoader() {
|
||||||
@@ -700,6 +701,13 @@ public final class Application {
|
|||||||
return HttpRpcClient.class;
|
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) {
|
private void registerResourceEnvs(boolean first, Properties... envs) {
|
||||||
@@ -731,7 +739,11 @@ public final class Application {
|
|||||||
AutoLoad auto = en.getType().getAnnotation(AutoLoad.class);
|
AutoLoad auto = en.getType().getAnnotation(AutoLoad.class);
|
||||||
if (auto == null || auto.value()) {
|
if (auto == null || auto.value()) {
|
||||||
int c = RetCodes.load(en.getType());
|
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();
|
this.onAppPreShutdown();
|
||||||
stopServers();
|
stopServers();
|
||||||
this.propertiesModule.destroy();
|
this.propertiesModule.destroy();
|
||||||
if (this.workExecutor != null) {
|
this.workExecutor.shutdownNow();
|
||||||
this.workExecutor.shutdownNow();
|
|
||||||
}
|
|
||||||
if (this.clientAsyncGroup != null) {
|
if (this.clientAsyncGroup != null) {
|
||||||
long s = System.currentTimeMillis();
|
long s = System.currentTimeMillis();
|
||||||
this.clientAsyncGroup.dispose();
|
this.clientAsyncGroup.dispose();
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ class NodeWebSocketNodeLoader implements ResourceTypeLoader {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sncpResFactory = ns.resourceFactory;
|
sncpResFactory = ns.resourceFactory;
|
||||||
loader = sncpResFactory.findTypeLoader(WebSocketNode.class, field);
|
loader = sncpResFactory.findResourceTypeLoader(WebSocketNode.class, field);
|
||||||
if (loader != null) {
|
if (loader != null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/main/java/org/redkale/inject/Configuration.java
Normal file
15
src/main/java/org/redkale/inject/Configuration.java
Normal 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 {}
|
||||||
@@ -18,6 +18,7 @@ import java.util.logging.*;
|
|||||||
import org.redkale.annotation.*;
|
import org.redkale.annotation.*;
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
import org.redkale.util.Creator;
|
||||||
import org.redkale.util.RedkaleClassLoader;
|
import org.redkale.util.RedkaleClassLoader;
|
||||||
import org.redkale.util.RedkaleException;
|
import org.redkale.util.RedkaleException;
|
||||||
import org.redkale.util.TypeToken;
|
import org.redkale.util.TypeToken;
|
||||||
@@ -54,12 +55,16 @@ public final class ResourceFactory {
|
|||||||
|
|
||||||
private final List<WeakReference<ResourceFactory>> chidren = new CopyOnWriteArrayList<>();
|
private final List<WeakReference<ResourceFactory>> chidren = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<Type, ResourceTypeLoader> resTypeLoaderMap = new ConcurrentHashMap();
|
||||||
|
|
||||||
private final ConcurrentHashMap<Class<? extends Annotation>, ResourceAnnotationLoader> resAnnotationLoaderMap =
|
private final ConcurrentHashMap<Class<? extends Annotation>, ResourceAnnotationLoader> resAnnotationLoaderMap =
|
||||||
new ConcurrentHashMap();
|
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) {
|
private ResourceFactory(ResourceFactory parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
@@ -101,9 +106,9 @@ public final class ResourceFactory {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 清空当前ResourceFactory注入资源 */
|
/** 清空当前已注入资源的缓存 */
|
||||||
public void release() {
|
public void release() {
|
||||||
this.store.clear();
|
this.entryStore.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** inject时的锁 */
|
/** inject时的锁 */
|
||||||
@@ -155,6 +160,80 @@ public final class ResourceFactory {
|
|||||||
return rt2 == null ? clazz : rt2.value();
|
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=""注入到资源池中,并同步已被注入的资源
|
* 将对象指定类型且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(
|
private <A> A register(
|
||||||
final boolean autoSync,
|
final boolean autoSync,
|
||||||
final String name,
|
final String name,
|
||||||
@@ -593,7 +750,8 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
} while ((c = c.getSuperclass()) != Object.class);
|
} 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);
|
ResourceEntry re = map.get(name);
|
||||||
if (re == null) {
|
if (re == null) {
|
||||||
map.put(name, new ResourceEntry(name, val));
|
map.put(name, new ResourceEntry(name, val));
|
||||||
@@ -613,7 +771,7 @@ public final class ResourceFactory {
|
|||||||
* @return 是否存在
|
* @return 是否存在
|
||||||
*/
|
*/
|
||||||
public <A> boolean contains(boolean recursive, String name, Class<? extends A> clazz) {
|
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) {
|
if (map != null) {
|
||||||
return map.containsKey(name);
|
return map.containsKey(name);
|
||||||
}
|
}
|
||||||
@@ -628,7 +786,7 @@ public final class ResourceFactory {
|
|||||||
* @return ResourceFactory
|
* @return ResourceFactory
|
||||||
*/
|
*/
|
||||||
public ResourceFactory findResourceFactory(String name, Type clazz) {
|
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)) {
|
if (map != null && map.containsKey(name)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -638,6 +796,78 @@ public final class ResourceFactory {
|
|||||||
return null;
|
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) {
|
public <A> A find(Class<? extends A> clazz) {
|
||||||
return find("", clazz);
|
return find("", clazz);
|
||||||
}
|
}
|
||||||
@@ -657,7 +887,7 @@ public final class ResourceFactory {
|
|||||||
if (rs != null) {
|
if (rs != null) {
|
||||||
return rs;
|
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)) {
|
if (!(en.getKey() instanceof Class)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -672,8 +902,8 @@ public final class ResourceFactory {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResourceEntry findEntry(String name, Type clazz) {
|
private <A> ResourceEntry<A> findEntry(String name, Type clazz) {
|
||||||
Map<String, ResourceEntry> map = this.store.get(clazz);
|
Map<String, ResourceEntry> map = this.entryStore.get(clazz);
|
||||||
if (map != null) {
|
if (map != null) {
|
||||||
ResourceEntry re = map.get(name);
|
ResourceEntry re = map.get(name);
|
||||||
if (re != null) {
|
if (re != null) {
|
||||||
@@ -686,27 +916,44 @@ public final class ResourceFactory {
|
|||||||
return null;
|
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);
|
return load("", clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载资源对象, 没有返回null
|
||||||
|
*
|
||||||
|
* @param <A> 泛型
|
||||||
|
* @param name 资源名
|
||||||
|
* @param clazz 资源类型
|
||||||
|
* @return 资源对象
|
||||||
|
*
|
||||||
|
* @since 2.8.0
|
||||||
|
*/
|
||||||
public <A> A load(String name, Type clazz) {
|
public <A> A load(String name, Type clazz) {
|
||||||
A val = find(name, clazz);
|
A val = find(name, clazz);
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
ResourceTypeLoader loader = findResourceTypeLoader(clazz);
|
Map<String, Supplier> supplierMap = this.resConfigureSupplierMap.get(clazz);
|
||||||
if (loader != null) {
|
Supplier supplier = supplierMap == null ? null : supplierMap.get(name);
|
||||||
val = (A) loader.load(this, null, null, name, null, null);
|
if (supplier != null) {
|
||||||
}
|
val = (A) supplier.get();
|
||||||
}
|
if (val != null) {
|
||||||
return val;
|
inject(name, val);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
public <A> A load(String name, Class<? extends A> clazz) {
|
ResourceTypeLoader loader = findResourceTypeLoader(clazz, (Field) null);
|
||||||
A val = find(name, clazz);
|
if (loader != null) {
|
||||||
if (val == null) {
|
val = (A) loader.load(this, null, null, name, null, null);
|
||||||
ResourceTypeLoader loader = findResourceTypeLoader(clazz);
|
}
|
||||||
if (loader != null) {
|
|
||||||
val = (A) loader.load(this, null, null, name, null, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@@ -721,7 +968,7 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private <A> List<A> query(final List<A> list, Type clazz) {
|
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) {
|
if (map != null) {
|
||||||
for (ResourceEntry re : map.values()) {
|
for (ResourceEntry re : map.values()) {
|
||||||
if (re.value != null) {
|
if (re.value != null) {
|
||||||
@@ -743,7 +990,7 @@ public final class ResourceFactory {
|
|||||||
if (predicate == null) {
|
if (predicate == null) {
|
||||||
return list;
|
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()) {
|
for (Map.Entry<String, ResourceEntry> en : map.entrySet()) {
|
||||||
if (predicate.test(en.getKey(), en.getValue().value)) {
|
if (predicate.test(en.getKey(), en.getValue().value)) {
|
||||||
list.add((A) en.getValue().value);
|
list.add((A) en.getValue().value);
|
||||||
@@ -756,48 +1003,98 @@ public final class ResourceFactory {
|
|||||||
return list;
|
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);
|
* @param srcObj 资源依附对象
|
||||||
if (rs != null) {
|
* @return 是否成功注入
|
||||||
return rs;
|
*/
|
||||||
}
|
|
||||||
}
|
|
||||||
if (parent != null) {
|
|
||||||
return parent.findEntry(name, clazz);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean inject(final Object srcObj) {
|
public boolean inject(final Object srcObj) {
|
||||||
return inject(srcObj, null);
|
return inject(srcObj, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入资源对象
|
||||||
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
|
* @param srcObj 资源依附对象
|
||||||
|
* @param attachment 附加对象
|
||||||
|
* @return 是否成功注入
|
||||||
|
*/
|
||||||
public <T> boolean inject(final Object srcObj, final T attachment) {
|
public <T> boolean inject(final Object srcObj, final T attachment) {
|
||||||
return inject(srcObj, attachment, null);
|
return inject(srcObj, attachment, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入资源对象
|
||||||
|
*
|
||||||
|
* @param srcObj 资源依附对象
|
||||||
|
* @param consumer 字段处理函数
|
||||||
|
* @return 是否成功注入
|
||||||
|
*/
|
||||||
public boolean inject(final Object srcObj, final BiConsumer<Object, Field> consumer) {
|
public boolean inject(final Object srcObj, final BiConsumer<Object, Field> consumer) {
|
||||||
return inject(srcObj, null, 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) {
|
public <T> boolean inject(final Object srcObj, final T attachment, final BiConsumer<Object, Field> consumer) {
|
||||||
return inject(null, srcObj, attachment, consumer, new ArrayList());
|
return inject(null, srcObj, attachment, consumer, new ArrayList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入资源对象
|
||||||
|
*
|
||||||
|
* @param srcResourceName 资源名
|
||||||
|
* @param srcObj 资源依附对象
|
||||||
|
* @return 是否成功注入
|
||||||
|
*/
|
||||||
public boolean inject(final String srcResourceName, final Object srcObj) {
|
public boolean inject(final String srcResourceName, final Object srcObj) {
|
||||||
return inject(srcResourceName, srcObj, null);
|
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) {
|
public <T> boolean inject(final String srcResourceName, final Object srcObj, final T attachment) {
|
||||||
return inject(srcResourceName, srcObj, attachment, null);
|
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) {
|
public boolean inject(final String srcResourceName, final Object srcObj, final BiConsumer<Object, Field> consumer) {
|
||||||
return inject(srcResourceName, srcObj, null, consumer);
|
return inject(srcResourceName, srcObj, null, consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入资源对象
|
||||||
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
|
* @param srcResourceName 资源名
|
||||||
|
* @param srcObj 资源依附对象
|
||||||
|
* @param attachment 附加对象
|
||||||
|
* @param consumer 字段处理函数
|
||||||
|
* @return 是否成功注入
|
||||||
|
*/
|
||||||
public <T> boolean inject(
|
public <T> boolean inject(
|
||||||
final String srcResourceName,
|
final String srcResourceName,
|
||||||
final Object srcObj,
|
final Object srcObj,
|
||||||
@@ -806,61 +1103,17 @@ public final class ResourceFactory {
|
|||||||
return inject(srcResourceName, srcObj, attachment, consumer, new ArrayList());
|
return inject(srcResourceName, srcObj, attachment, consumer, new ArrayList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getResourceName(String name) {
|
/**
|
||||||
return getResourceName(null, name);
|
* 注入资源对象
|
||||||
}
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
public static String getResourceName(String parent, String name) {
|
* @param srcResourceName 资源名
|
||||||
if (name == null) {
|
* @param srcObj 资源依附对象
|
||||||
return null;
|
* @param attachment 附加对象
|
||||||
}
|
* @param consumer 字段处理函数
|
||||||
if (name.startsWith("${")) {
|
* @param list 层级对象集合
|
||||||
String subName = name.substring(2);
|
* @return 是否成功注入
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> boolean inject(
|
private <T> boolean inject(
|
||||||
String srcResourceName,
|
String srcResourceName,
|
||||||
Object srcObj,
|
Object srcObj,
|
||||||
@@ -1017,17 +1270,19 @@ public final class ResourceFactory {
|
|||||||
&& rcname.startsWith("property.")) { // 兼容2.8.0之前版本自动追加property.开头的配置项
|
&& rcname.startsWith("property.")) { // 兼容2.8.0之前版本自动追加property.开头的配置项
|
||||||
re = findEntry(rcname.substring("property.".length()), String.class);
|
re = findEntry(rcname.substring("property.".length()), String.class);
|
||||||
} else {
|
} else {
|
||||||
re = findEntry(rcname, classType);
|
rs = findEntry(rcname, classType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (re == null) {
|
if (re == null) {
|
||||||
ResourceTypeLoader it = findTypeLoader(gencType, field);
|
ResourceTypeLoader it = findResourceTypeLoader(gencType, field);
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
rs = it.load(this, srcResourceName, srcObj, rcname, field, attachment);
|
rs = it.load(this, srcResourceName, srcObj, rcname, field, attachment);
|
||||||
autoRegNull = it.autoNone();
|
autoRegNull = it.autoNone();
|
||||||
if (rs == null) {
|
if (rs == null) {
|
||||||
re = findEntry(rcname, gencType);
|
re = findEntry(rcname, gencType);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
rs = load(rcname, gencType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rs == null && re == null && gencType != classType) {
|
if (rs == null && re == null && gencType != classType) {
|
||||||
@@ -1049,17 +1304,19 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (re == null) {
|
if (re == null) {
|
||||||
ResourceTypeLoader it = findTypeLoader(classType, field);
|
ResourceTypeLoader it = findResourceTypeLoader(classType, field);
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
rs = it.load(this, srcResourceName, srcObj, rcname, field, attachment);
|
rs = it.load(this, srcResourceName, srcObj, rcname, field, attachment);
|
||||||
autoRegNull = it.autoNone();
|
autoRegNull = it.autoNone();
|
||||||
if (rs == null) {
|
if (rs == null) {
|
||||||
re = findEntry(rcname, classType);
|
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("${")) {
|
if (rcname.startsWith("${")) {
|
||||||
String sub = rcname.substring(rcname.lastIndexOf("${") + 2, rcname.lastIndexOf('}'));
|
String sub = rcname.substring(rcname.lastIndexOf("${") + 2, rcname.lastIndexOf('}'));
|
||||||
register(sub, gencType, null); // 自动注入null的值
|
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);
|
* 获取最底层ResourceFactory
|
||||||
parentRoot().resAnnotationLoaderMap.put(loader.annotationType(), loader);
|
*
|
||||||
}
|
* @return ResourceFactory
|
||||||
|
*/
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResourceFactory parentRoot() {
|
private ResourceFactory parentRoot() {
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
return this;
|
return this;
|
||||||
@@ -1135,35 +1375,14 @@ public final class ResourceFactory {
|
|||||||
return parent.parentRoot();
|
return parent.parentRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResourceTypeLoader findMatchTypeLoader(Type ft, @Nullable Field field) {
|
/**
|
||||||
ResourceTypeLoader it = this.resTypeLoaderMap.get(ft);
|
* 调用标记ResourceInjected的监听方法
|
||||||
if (it == null && field != null) {
|
*
|
||||||
it = this.resTypeLoaderMap.get(field.getType());
|
* @param dest 资源的依附对象
|
||||||
}
|
* @param field 资源的依附对象的字段
|
||||||
if (it != null) {
|
* @param res 资源对象
|
||||||
return it;
|
*/
|
||||||
}
|
private void onResourceInjected(Object dest, Field field, Object res) {
|
||||||
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) {
|
|
||||||
if (res == null
|
if (res == null
|
||||||
|| res.getClass().isPrimitive()
|
|| res.getClass().isPrimitive()
|
||||||
|| res.getClass().getName().startsWith("java.")
|
|| res.getClass().getName().startsWith("java.")
|
||||||
@@ -1179,7 +1398,7 @@ public final class ResourceFactory {
|
|||||||
Object[] params = new Object[paramTypes.length];
|
Object[] params = new Object[paramTypes.length];
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (int i = 0; i < params.length; i++) {
|
||||||
if (paramTypes[i] == Object.class) {
|
if (paramTypes[i] == Object.class) {
|
||||||
params[i] = src;
|
params[i] = dest;
|
||||||
} else if (paramTypes[i] == String.class) {
|
} else if (paramTypes[i] == String.class) {
|
||||||
params[i] = field.getName();
|
params[i] = field.getName();
|
||||||
} else if (paramTypes[i] == Field.class) {
|
} else if (paramTypes[i] == Field.class) {
|
||||||
@@ -1200,6 +1419,11 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源依附信息的缓存对象
|
||||||
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
|
*/
|
||||||
private static class ResourceEntry<T> {
|
private static class ResourceEntry<T> {
|
||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
@@ -1267,6 +1491,11 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源字段和变更监听方法信息的缓存对象
|
||||||
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
|
*/
|
||||||
private static class ResourceElement<T> {
|
private static class ResourceElement<T> {
|
||||||
|
|
||||||
private static final ReentrantLock syncLock = new ReentrantLock();
|
private static final ReentrantLock syncLock = new ReentrantLock();
|
||||||
|
|||||||
78
src/test/java/org/redkale/test/inject/ConfigurationTest.java
Normal file
78
src/test/java/org/redkale/test/inject/ConfigurationTest.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user