ResourceListener支持对Environment环境变量的支持
This commit is contained in:
@@ -53,9 +53,9 @@ public abstract class PropertiesAgent {
|
|||||||
public abstract void destroy(AnyValue conf);
|
public abstract void destroy(AnyValue conf);
|
||||||
|
|
||||||
protected void updateEnvironmentProperties(Application application, Properties props) {
|
protected void updateEnvironmentProperties(Application application, Properties props) {
|
||||||
Properties notifyCache = new Properties();
|
Properties changeCache = new Properties();
|
||||||
props.forEach((k, v) -> application.updateEnvironmentProperty(k.toString(), v, notifyCache));
|
props.forEach((k, v) -> application.updateEnvironmentProperty(k.toString(), v, changeCache));
|
||||||
application.resourceFactory.register(notifyCache);
|
application.resourceFactory.register(changeCache, "", Environment.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void putEnvironmentProperty(Application application, String key, Object value) {
|
protected void putEnvironmentProperty(Application application, String key, Object value) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.util.function.BiConsumer;
|
|||||||
/**
|
/**
|
||||||
* 环境变量, 只读版Properties
|
* 环境变量, 只读版Properties
|
||||||
* 只存放system.property.、mimetype.property.、redkale.cachesource(.|[)、redkale.datasource(.|[)和其他非redkale.开头的配置项
|
* 只存放system.property.、mimetype.property.、redkale.cachesource(.|[)、redkale.datasource(.|[)和其他非redkale.开头的配置项
|
||||||
|
* 只有ResourceFactory.register(Properties properties, String environmentName, Class environmentType) 方法才能是Environment的ResourceListener起作用
|
||||||
*
|
*
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -347,12 +347,12 @@ public final class ResourceFactory {
|
|||||||
*
|
*
|
||||||
* @param <A> 泛型
|
* @param <A> 泛型
|
||||||
* @param name 资源名
|
* @param name 资源名
|
||||||
* @param rs 资源对象
|
* @param val 资源对象
|
||||||
*
|
*
|
||||||
* @return 旧资源对象
|
* @return 旧资源对象
|
||||||
*/
|
*/
|
||||||
public <A> A register(final String name, final A rs) {
|
public <A> A register(final String name, final A val) {
|
||||||
return register(true, name, rs);
|
return register(true, name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -361,19 +361,19 @@ public final class ResourceFactory {
|
|||||||
* @param <A> 泛型
|
* @param <A> 泛型
|
||||||
* @param autoSync 是否同步已被注入的资源
|
* @param autoSync 是否同步已被注入的资源
|
||||||
* @param name 资源名
|
* @param name 资源名
|
||||||
* @param rs 资源对象
|
* @param val 资源对象
|
||||||
*
|
*
|
||||||
* @return 旧资源对象
|
* @return 旧资源对象
|
||||||
*/
|
*/
|
||||||
public <A> A register(final boolean autoSync, final String name, final A rs) {
|
public <A> A register(final boolean autoSync, final String name, final A val) {
|
||||||
checkResourceName(name);
|
checkResourceName(name);
|
||||||
final Class<?> claz = rs.getClass();
|
final Class<?> claz = val.getClass();
|
||||||
ResourceType rtype = claz.getAnnotation(ResourceType.class);
|
ResourceType rtype = claz.getAnnotation(ResourceType.class);
|
||||||
if (rtype == null) {
|
if (rtype == null) {
|
||||||
return (A) register(autoSync, name, claz, rs);
|
return (A) register(autoSync, name, claz, val);
|
||||||
} else {
|
} else {
|
||||||
A old = null;
|
A old = null;
|
||||||
A t = (A) register(autoSync, name, rtype.value(), rs);
|
A t = (A) register(autoSync, name, rtype.value(), val);
|
||||||
if (t != null) old = t;
|
if (t != null) old = t;
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
@@ -385,12 +385,12 @@ public final class ResourceFactory {
|
|||||||
* @param <A> 泛型
|
* @param <A> 泛型
|
||||||
* @param name 资源名
|
* @param name 资源名
|
||||||
* @param clazz 资源类型
|
* @param clazz 资源类型
|
||||||
* @param rs 资源对象
|
* @param val 资源对象
|
||||||
*
|
*
|
||||||
* @return 旧资源对象
|
* @return 旧资源对象
|
||||||
*/
|
*/
|
||||||
public <A> A register(final String name, final Class<? extends A> clazz, final A rs) {
|
public <A> A register(final String name, final Class<? extends A> clazz, final A val) {
|
||||||
return register(true, name, clazz, rs);
|
return register(true, name, clazz, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -399,12 +399,12 @@ public final class ResourceFactory {
|
|||||||
* @param <A> 泛型
|
* @param <A> 泛型
|
||||||
* @param name 资源名
|
* @param name 资源名
|
||||||
* @param clazz 资源类型
|
* @param clazz 资源类型
|
||||||
* @param rs 资源对象
|
* @param val 资源对象
|
||||||
*
|
*
|
||||||
* @return 旧资源对象
|
* @return 旧资源对象
|
||||||
*/
|
*/
|
||||||
public <A> A register(final String name, final Type clazz, final A rs) {
|
public <A> A register(final String name, final Type clazz, final A val) {
|
||||||
return register(true, name, clazz, rs);
|
return register(true, name, clazz, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -414,12 +414,12 @@ public final class ResourceFactory {
|
|||||||
* @param autoSync 是否同步已被注入的资源
|
* @param autoSync 是否同步已被注入的资源
|
||||||
* @param name 资源名
|
* @param name 资源名
|
||||||
* @param clazz 资源类型
|
* @param clazz 资源类型
|
||||||
* @param rs 资源对象
|
* @param val 资源对象
|
||||||
*
|
*
|
||||||
* @return 旧资源对象
|
* @return 旧资源对象
|
||||||
*/
|
*/
|
||||||
public <A> A register(final boolean autoSync, final String name, final Type clazz, final A rs) {
|
public <A> A register(final boolean autoSync, final String name, final Type clazz, final A val) {
|
||||||
return register(autoSync, name, clazz, rs, null);
|
return register(autoSync, name, clazz, val, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -429,15 +429,47 @@ public final class ResourceFactory {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void register(Properties properties) {
|
public void register(Properties properties) {
|
||||||
|
register(properties, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将多个以指定资源名的String对象注入到资源池中
|
||||||
|
*
|
||||||
|
* @param properties 资源键值对
|
||||||
|
* @param environmentName 额外的资源名
|
||||||
|
* @param environmentType 额外的类名
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public <A> void register(Properties properties, String environmentName, Class<A> environmentType) {
|
||||||
if (properties == null) return;
|
if (properties == null) return;
|
||||||
List<ResourceChangeWrapper> wrappers = new ArrayList<>();
|
List<ResourceChangeWrapper> wrappers = new ArrayList<>();
|
||||||
properties.forEach((k, v) -> register(true, k.toString(), String.class, v, wrappers));
|
List<ResourceEvent> environmentEventList = new ArrayList<>();
|
||||||
if (wrappers.isEmpty()) return;
|
properties.forEach((k, v) -> {
|
||||||
|
Object old = register(true, k.toString(), String.class, v, wrappers);
|
||||||
|
if (!Objects.equals(v, old)) {
|
||||||
|
environmentEventList.add(new ResourceChangeEvent(k.toString(), v, old));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Map<Object, Method> envListenMap = new LinkedHashMap<>();
|
||||||
|
if (!environmentEventList.isEmpty() && environmentName != null && environmentType != null) {
|
||||||
|
ResourceEntry<A> entry = findEntry(environmentName, environmentType);
|
||||||
|
if (entry != null && entry.elements != null) {
|
||||||
|
for (ResourceElement element : entry.elements) {
|
||||||
|
Object dest = element.dest.get();
|
||||||
|
if (dest != null && element.listener != null) {
|
||||||
|
envListenMap.put(dest, element.listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wrappers.isEmpty() && envListenMap.isEmpty()) return;
|
||||||
Map<Object, List<ResourceChangeWrapper>> map = new LinkedHashMap<>();
|
Map<Object, List<ResourceChangeWrapper>> map = new LinkedHashMap<>();
|
||||||
for (ResourceChangeWrapper wrapper : wrappers) {
|
for (ResourceChangeWrapper wrapper : wrappers) {
|
||||||
map.computeIfAbsent(wrapper.dest, k -> new ArrayList<>()).add(wrapper);
|
map.computeIfAbsent(wrapper.dest, k -> new ArrayList<>()).add(wrapper);
|
||||||
}
|
}
|
||||||
|
if (!map.isEmpty()) {
|
||||||
map.forEach((dest, list) -> {
|
map.forEach((dest, list) -> {
|
||||||
|
if (envListenMap.containsKey(dest)) return; //跳过含有@Resource Environment字段的对象
|
||||||
Method listener = list.get(0).listener;
|
Method listener = list.get(0).listener;
|
||||||
try {
|
try {
|
||||||
ResourceEvent[] events = new ResourceEvent[list.size()];
|
ResourceEvent[] events = new ResourceEvent[list.size()];
|
||||||
@@ -451,28 +483,31 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (!envListenMap.isEmpty()) { //含有@Resource Environment字段的对象进行变更响应
|
||||||
|
ResourceEvent[] environmentEvents = environmentEventList.toArray(new ResourceEvent[environmentEventList.size()]);
|
||||||
|
envListenMap.forEach((dest, listener) -> {
|
||||||
|
try {
|
||||||
|
Object[] ps = new Object[]{environmentEvents};
|
||||||
|
listener.invoke(dest, ps);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.SEVERE, dest + " resource change listener error", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private <A> A register(final boolean autoSync, final String name, final Type clazz, final A rs, List<ResourceChangeWrapper> wrappers) {
|
private <A> A register(final boolean autoSync, final String name, final Type clazz, final A val, List<ResourceChangeWrapper> wrappers) {
|
||||||
checkResourceName(name);
|
checkResourceName(name);
|
||||||
Class clz = TypeToken.typeToClass(clazz);
|
Class clz = TypeToken.typeToClass(clazz);
|
||||||
if (clz != null && !clz.isPrimitive() && rs != null && !clz.isAssignableFrom(rs.getClass())) {
|
if (clz != null && !clz.isPrimitive() && val != null && !clz.isAssignableFrom(val.getClass())) {
|
||||||
throw new RuntimeException(clz + "not isAssignableFrom (" + rs + ") class " + rs.getClass());
|
throw new RuntimeException(clz + "not isAssignableFrom (" + val + ") class " + val.getClass());
|
||||||
}
|
|
||||||
ConcurrentHashMap<String, ResourceEntry> map = this.store.get(clazz);
|
|
||||||
if (map == null) {
|
|
||||||
synchronized (clazz) {
|
|
||||||
map = this.store.get(clazz);
|
|
||||||
if (map == null) {
|
|
||||||
map = new ConcurrentHashMap();
|
|
||||||
store.put(clazz, map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ConcurrentHashMap<String, ResourceEntry> map = this.store.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, rs));
|
map.put(name, new ResourceEntry(name, val));
|
||||||
} else {
|
} else {
|
||||||
map.put(name, new ResourceEntry(name, rs, re.elements, wrappers, autoSync));
|
map.put(name, new ResourceEntry(name, val, re.elements, wrappers, autoSync));
|
||||||
}
|
}
|
||||||
return re == null ? null : (A) re.value;
|
return re == null ? null : (A) re.value;
|
||||||
}
|
}
|
||||||
@@ -630,11 +665,11 @@ public final class ResourceFactory {
|
|||||||
int pos = name.indexOf("{system.property.");
|
int pos = name.indexOf("{system.property.");
|
||||||
if (pos < 0) return (name.contains(RESOURCE_PARENT_NAME) && parent != null) ? name.replace(RESOURCE_PARENT_NAME, parent) : name;
|
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 prefix = name.substring(0, pos);
|
||||||
String subname = name.substring(pos + "{system.property.".length());
|
String subName = name.substring(pos + "{system.property.".length());
|
||||||
pos = subname.lastIndexOf('}');
|
pos = subName.lastIndexOf('}');
|
||||||
if (pos < 0) return (name.contains(RESOURCE_PARENT_NAME) && parent != null) ? name.replace(RESOURCE_PARENT_NAME, parent) : name;
|
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 postfix = subName.substring(pos + 1);
|
||||||
String property = subname.substring(0, pos);
|
String property = subName.substring(0, pos);
|
||||||
return formatResourceName(parent, prefix + System.getProperty(property, "") + postfix);
|
return formatResourceName(parent, prefix + System.getProperty(property, "") + postfix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,7 +739,7 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
boolean autoregnull = true;
|
boolean autoRegNull = true;
|
||||||
final String rcname = formatResourceName(srcResourceName, tname);
|
final String rcname = formatResourceName(srcResourceName, tname);
|
||||||
Object rs;
|
Object rs;
|
||||||
if (rcname.startsWith("system.property.")) {
|
if (rcname.startsWith("system.property.")) {
|
||||||
@@ -722,7 +757,7 @@ public final class ResourceFactory {
|
|||||||
ResourceTypeLoader it = findTypeLoader(genctype, field);
|
ResourceTypeLoader it = findTypeLoader(genctype, field);
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
it.load(this, srcResourceName, srcObj, rcname, field, attachment);
|
it.load(this, srcResourceName, srcObj, rcname, field, attachment);
|
||||||
autoregnull = it.autoNone();
|
autoRegNull = it.autoNone();
|
||||||
re = findEntry(rcname, genctype);
|
re = findEntry(rcname, genctype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -739,12 +774,12 @@ public final class ResourceFactory {
|
|||||||
ResourceTypeLoader it = findTypeLoader(classtype, field);
|
ResourceTypeLoader it = findTypeLoader(classtype, field);
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
it.load(this, srcResourceName, srcObj, rcname, field, attachment);
|
it.load(this, srcResourceName, srcObj, rcname, field, attachment);
|
||||||
autoregnull = it.autoNone();
|
autoRegNull = it.autoNone();
|
||||||
re = findEntry(rcname, classtype);
|
re = findEntry(rcname, classtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (re == null && autoregnull) {
|
if (re == null && autoRegNull) {
|
||||||
register(rcname, genctype, null); //自动注入null的值
|
register(rcname, genctype, null); //自动注入null的值
|
||||||
re = findEntry(rcname, genctype);
|
re = findEntry(rcname, genctype);
|
||||||
}
|
}
|
||||||
@@ -867,7 +902,7 @@ public final class ResourceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//wrappers=null时才会触发listener的ResourceChangeEvent事件
|
//wrappers=null时才会触发listener的ResourceChangeEvent事件
|
||||||
public ResourceEntry(final String name, T value, final List<ResourceElement> elements, List<ResourceChangeWrapper> wrappers, boolean sync) {
|
public ResourceEntry(final String name, T value, final List<ResourceElement> elements, Collection<ResourceChangeWrapper> wrappers, boolean sync) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.elements = elements == null ? new CopyOnWriteArrayList<>() : elements;
|
this.elements = elements == null ? new CopyOnWriteArrayList<>() : elements;
|
||||||
@@ -1001,6 +1036,24 @@ public final class ResourceFactory {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
hash = 97 * hash + Objects.hashCode(this.dest);
|
||||||
|
hash = 97 * hash + Objects.hashCode(this.listener);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null) return false;
|
||||||
|
if (getClass() != obj.getClass()) return false;
|
||||||
|
final ResourceChangeWrapper other = (ResourceChangeWrapper) obj;
|
||||||
|
if (!Objects.equals(this.dest, other.dest)) return false;
|
||||||
|
return Objects.equals(this.listener, other.listener);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ResourceChangeEvent<T> implements ResourceEvent<T> {
|
private static class ResourceChangeEvent<T> implements ResourceEvent<T> {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import static java.lang.annotation.ElementType.METHOD;
|
|||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Resource资源被更新时的监听事件。本注解只能标记在方法参数为ResourceEvent[]上。
|
* @Resource资源被更新时的监听事件, 本注解只能标记在方法参数为ResourceEvent[]上 <br>
|
||||||
|
* 注意: 一个类只能存在一个@ResourceResourceListener的方法, 多余的会被忽略。
|
||||||
* 方法在资源被更新以后调用。
|
* 方法在资源被更新以后调用。
|
||||||
*
|
*
|
||||||
* <blockquote><pre>
|
* <blockquote><pre>
|
||||||
|
|||||||
129
src/test/java/org/redkale/test/util/ResourceListenerTest.java
Normal file
129
src/test/java/org/redkale/test/util/ResourceListenerTest.java
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
*/
|
||||||
|
package org.redkale.test.util;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.redkale.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class ResourceListenerTest {
|
||||||
|
|
||||||
|
private boolean main;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
ResourceListenerTest test = new ResourceListenerTest();
|
||||||
|
test.main = true;
|
||||||
|
test.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void run() throws Exception {
|
||||||
|
AtomicInteger aCounter = new AtomicInteger();
|
||||||
|
Properties env = new Properties();
|
||||||
|
env.put("property.id", "2345");
|
||||||
|
ResourceFactory factory = ResourceFactory.create();
|
||||||
|
factory.register(new Environment(env));
|
||||||
|
|
||||||
|
AService aservice = new AService();
|
||||||
|
BService bservice = new BService();
|
||||||
|
ABService abservice = new ABService();
|
||||||
|
|
||||||
|
factory.inject(aservice);
|
||||||
|
factory.inject(bservice);
|
||||||
|
factory.inject(abservice);
|
||||||
|
|
||||||
|
Properties prop = new Properties();
|
||||||
|
prop.put("property.id", "7890");
|
||||||
|
prop.put("property.name", "my name");
|
||||||
|
factory.register(prop, "", Environment.class);
|
||||||
|
|
||||||
|
if (!main) {
|
||||||
|
Assertions.assertTrue(aservice.counter.get() == 1);
|
||||||
|
Assertions.assertTrue(bservice.counter.get() == 2);
|
||||||
|
Assertions.assertTrue(abservice.counter.get() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory.register("property.id", "7777");
|
||||||
|
|
||||||
|
if (!main) {
|
||||||
|
Assertions.assertTrue(aservice.counter.get() == 2);
|
||||||
|
Assertions.assertTrue(bservice.counter.get() == 2);
|
||||||
|
Assertions.assertTrue(abservice.counter.get() == 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AService {
|
||||||
|
|
||||||
|
public final AtomicInteger counter = new AtomicInteger();
|
||||||
|
|
||||||
|
@Resource(name = "property.id")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Resource(name = "property.desc")
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
@ResourceListener
|
||||||
|
private void changeResource(ResourceEvent[] events) {
|
||||||
|
for (ResourceEvent event : events) {
|
||||||
|
counter.incrementAndGet();
|
||||||
|
System.out.println(getClass().getSimpleName() + " @Resource = " + event.name() + " 资源变更: newVal = " + event.newValue() + ", oldVal = " + event.oldValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String test() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class BService {
|
||||||
|
|
||||||
|
public final AtomicInteger counter = new AtomicInteger();
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private Environment env;
|
||||||
|
|
||||||
|
@ResourceListener
|
||||||
|
private void changeResource(ResourceEvent[] events) {
|
||||||
|
for (ResourceEvent event : events) {
|
||||||
|
counter.incrementAndGet();
|
||||||
|
System.out.println(getClass().getSimpleName() + " @Resource = " + event.name() + " 资源变更: newVal = " + event.newValue() + ", oldVal = " + event.oldValue());
|
||||||
|
}
|
||||||
|
System.out.println(getClass().getSimpleName() + " env = " + env);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String test() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ABService {
|
||||||
|
|
||||||
|
public final AtomicInteger counter = new AtomicInteger();
|
||||||
|
|
||||||
|
@Resource(name = "property.id")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private Environment env;
|
||||||
|
|
||||||
|
@ResourceListener
|
||||||
|
private void changeResource(ResourceEvent[] events) {
|
||||||
|
for (ResourceEvent event : events) {
|
||||||
|
counter.incrementAndGet();
|
||||||
|
System.out.println(getClass().getSimpleName() + " @Resource = " + event.name() + " 资源变更: newVal = " + event.newValue() + ", oldVal = " + event.oldValue());
|
||||||
|
}
|
||||||
|
System.out.println(getClass().getSimpleName() + " env = " + env);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String test() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user