This commit is contained in:
Redkale
2016-08-20 12:33:23 +08:00
parent 42c188867a
commit 3d0bd3a5c2
3 changed files with 122 additions and 26 deletions

View File

@@ -175,7 +175,7 @@ public final class ResourceFactory {
if (re == null) {
map.put(name, new ResourceEntry(rs));
} else {
map.put(name, new ResourceEntry(rs, re.elements, autoSync));
map.put(name, new ResourceEntry(rs, name, re.elements, autoSync));
}
return re == null ? null : (A) re.value;
}
@@ -405,7 +405,7 @@ public final class ResourceFactory {
this.elements = new CopyOnWriteArrayList<>();
}
public ResourceEntry(T value, final List<ResourceElement> elements, boolean sync) {
public ResourceEntry(T value, final String name, final List<ResourceElement> elements, boolean sync) {
this.value = value;
this.elements = elements == null ? new CopyOnWriteArrayList<>() : elements;
if (sync && elements != null && !elements.isEmpty()) {
@@ -433,11 +433,26 @@ public final class ResourceFactory {
}
}
if (rs == null && classtype.isPrimitive()) rs = Array.get(Array.newInstance(classtype, 1), 0);
Object oldVal = null;
if (element.listener != null) {
try {
oldVal = element.field.get(dest);
} catch (Exception e) {
e.printStackTrace();
}
}
try {
element.field.set(dest, rs);
} catch (Exception e) {
e.printStackTrace();
}
if (element.listener != null) {
try {
element.listener.invoke(dest, name, rs, oldVal);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
@@ -445,16 +460,41 @@ public final class ResourceFactory {
private static class ResourceElement<T> {
private static final HashMap<Class, Method> listenerMethods = new HashMap<>(); //不使用ConcurrentHashMap是因为value不能存null
public final WeakReference<T> dest;
public final Field field;
public final Field field; //Resource 字段
public final Class fieldType;
public final Method listener;
public ResourceElement(T dest, Field field) {
this.dest = new WeakReference(dest);
this.field = field;
this.fieldType = field.getType();
Class t = dest.getClass();
String tn = t.getName();
this.listener = tn.startsWith("java.") || tn.startsWith("javax.") ? null : findListener(t);
}
private static synchronized Method findListener(Class clazz) {
Class loop = clazz;
Method m = null;
do {
for (Method method : loop.getDeclaredMethods()) {
if (method.getAnnotation(ResourceListener.class) != null
&& method.getParameterCount() == 3
&& String.class.isAssignableFrom(method.getParameterTypes()[0])) {
m = method;
m.setAccessible(true);
break;
}
}
} while ((loop = loop.getSuperclass()) != Object.class);
listenerMethods.put(clazz, m);
return m;
}
}

View File

@@ -0,0 +1,51 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.util;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* &#64;Resource资源被更新时的监听事件。改注解只能标记在方法参数为(String name, T newVal, T oldVal)上。
*
* <blockquote><pre>
* public class Record {
*
* &#64;Resource(name = "record.id")
* private int id;
*
* &#64;Resource(name = "record.name")
* private String name;
*
* &#64;ResourceListener
* private void changeResource(String name, Object newVal, Object oldVal) {
* System.out.println("@Resource = " + name + " 资源变更: newVal = " + newVal + ", oldVal = " + oldVal);
* }
*
* public static void main(String[] args) throws Exception {
* ResourceFactory factory = ResourceFactory.root();
* factory.register("record.id", "2345");
* factory.register("record.name", "my old name");
* Record record = new Record();
* factory.inject(record);
* factory.register("record.name", "my new name");
* }
*
* }
* </pre></blockquote>
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Documented
@Target({METHOD})
@Retention(RUNTIME)
public @interface ResourceListener {
}