diff --git a/src/org/redkale/util/ResourceFactory.java b/src/org/redkale/util/ResourceFactory.java index c24368a1a..48b081844 100644 --- a/src/org/redkale/util/ResourceFactory.java +++ b/src/org/redkale/util/ResourceFactory.java @@ -5,6 +5,7 @@ */ package org.redkale.util; +import java.lang.ref.*; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; @@ -33,9 +34,9 @@ public final class ResourceFactory { private final ConcurrentHashMap loadermap = new ConcurrentHashMap(); - private final ConcurrentHashMap, ConcurrentHashMap> store = new ConcurrentHashMap(); + private final ConcurrentHashMap, ConcurrentHashMap> store = new ConcurrentHashMap(); - private final ConcurrentHashMap> gencstore = new ConcurrentHashMap(); + private final ConcurrentHashMap> gencstore = new ConcurrentHashMap(); private ResourceFactory(ResourceFactory parent) { this.parent = parent; @@ -79,13 +80,18 @@ public final class ResourceFactory { } public void register(final String name, final Class clazz, final A rs) { - ConcurrentHashMap map = this.store.get(clazz); + ConcurrentHashMap map = this.store.get(clazz); if (map == null) { - ConcurrentHashMap sub = new ConcurrentHashMap(); - sub.put(name, rs); + ConcurrentHashMap sub = new ConcurrentHashMap(); + sub.put(name, new ResourceEntry(rs)); store.put(clazz, sub); } else { - map.put(name, rs); + ResourceEntry re = map.get(name); + if (re == null) { + map.put(name, new ResourceEntry(rs)); + } else { + map.put(name, new ResourceEntry(rs, re.elements)); + } } } @@ -94,13 +100,18 @@ public final class ResourceFactory { register(name, (Class) clazz, rs); return; } - ConcurrentHashMap map = this.gencstore.get(clazz); + ConcurrentHashMap map = this.gencstore.get(clazz); if (map == null) { - ConcurrentHashMap sub = new ConcurrentHashMap(); - sub.put(name, rs); + ConcurrentHashMap sub = new ConcurrentHashMap(); + sub.put(name, new ResourceEntry(rs)); gencstore.put(clazz, sub); } else { - map.put(name, rs); + ResourceEntry re = map.get(name); + if (re == null) { + map.put(name, new ResourceEntry(rs)); + } else { + map.put(name, new ResourceEntry(rs, re.elements)); + } } } @@ -109,32 +120,42 @@ public final class ResourceFactory { } public A find(String name, Type clazz) { - Map map = this.gencstore.get(clazz); + ResourceEntry re = findEntry(name, clazz); + return re == null ? null : (A) re.value; + } + + private ResourceEntry findEntry(String name, Type clazz) { + Map map = this.gencstore.get(clazz); if (map != null) { - A rs = (A) map.get(name); - if (rs != null) return rs; + ResourceEntry re = map.get(name); + if (re != null) return re; } - if (parent != null) return parent.find(name, clazz); + if (parent != null) return parent.findEntry(name, clazz); return null; } public A find(String name, Class clazz) { - Map map = this.store.get(clazz); + ResourceEntry re = findEntry(name, clazz); + return re == null ? null : re.value; + } + + private ResourceEntry findEntry(String name, Class clazz) { + Map map = this.store.get(clazz); if (map != null) { - A rs = (A) map.get(name); + ResourceEntry rs = map.get(name); if (rs != null) return rs; } - if (parent != null) return parent.find(name, clazz); + if (parent != null) return parent.findEntry(name, clazz); return null; } public A findChild(final String name, final Class clazz) { A rs = find(name, clazz); if (rs != null) return rs; - for (Map.Entry, ConcurrentHashMap> en : this.store.entrySet()) { //不用forEach为兼容JDK 6 + for (Map.Entry, ConcurrentHashMap> en : this.store.entrySet()) { //不用forEach为兼容JDK 6 if (!clazz.isAssignableFrom(en.getKey())) continue; - Object v = en.getValue().get(name); - if (v != null) return (A) v; + ResourceEntry v = en.getValue().get(name); + if (v != null) return (A) v.value; } return null; } @@ -146,11 +167,13 @@ public final class ResourceFactory { } private void load(final Pattern reg, Class clazz, final A exclude, final Map result) { - ConcurrentHashMap map = this.store.get(clazz); + ConcurrentHashMap map = this.store.get(clazz); if (map != null) { - for (Map.Entry en : map.entrySet()) { // 不用forEach为兼容JDK 6 + for (Map.Entry en : map.entrySet()) { // 不用forEach为兼容JDK 6 String x = en.getKey(); - Object y = en.getValue(); + ResourceEntry re = en.getValue(); + if (re == null) continue; + Object y = re.value; if (y != exclude && reg.matcher(x).find() && result.get(x) == null) result.put(x, (A) y); } } @@ -207,22 +230,25 @@ public final class ResourceFactory { } } final String rcname = tname; - Object rs = genctype == classtype ? null : find(rcname, genctype); - if (rs == null) { + ResourceEntry re = genctype == classtype ? null : findEntry(rcname, genctype); + if (re == null) { if (Map.class.isAssignableFrom(classtype)) { - rs = find(Pattern.compile(rcname.isEmpty() ? ".*" : rcname), (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[1], src); + Map map = find(Pattern.compile(rcname.isEmpty() ? ".*" : rcname), (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[1], src); + if (map != null) re = new ResourceEntry(map); } else if (rcname.startsWith("property.")) { - rs = find(rcname, String.class); + re = findEntry(rcname, String.class); } else { - rs = find(rcname, classtype); + re = findEntry(rcname, classtype); } } - if (rs == null) { + if (re == null) { ResourceLoader it = findLoader(field.getGenericType(), field); - rs = it.load(this, src, rcname, field, attachment); + Object rs = it.load(this, src, rcname, field, attachment); + if (rs != null) re = genctype == classtype ? findEntry(rcname, classtype) : findEntry(rcname, genctype); } - if (rs == null) continue; - if (!rs.getClass().isPrimitive() && classtype.isPrimitive()) { + if (re == null) continue; + Object rs = re.value; + if (!re.value.getClass().isPrimitive() && classtype.isPrimitive()) { if (classtype == int.class) { rs = Integer.decode(rs.toString()); } else if (classtype == long.class) { @@ -240,6 +266,7 @@ public final class ResourceFactory { } } field.set(src, rs); + re.elements.add(new ResourceElement<>(src, field)); } } while ((clazz = clazz.getSuperclass()) != Object.class); return true; @@ -261,6 +288,69 @@ public final class ResourceFactory { return parent == null ? null : parent.findLoader(ft, field); } + private static class ResourceEntry { + + public final T value; + + public final List elements; + + public ResourceEntry(T value) { + this.value = value; + this.elements = new CopyOnWriteArrayList<>(); + } + + public ResourceEntry(T value, final List elements) { + this.value = value; + this.elements = elements == null ? new CopyOnWriteArrayList<>() : elements; + if (elements != null && !elements.isEmpty()) { + + for (ResourceElement element : elements) { + Object dest = element.dest.get(); + if (dest == null) continue; + Object rs = value; + final Class classtype = element.fieldType; + if (rs != null && !rs.getClass().isPrimitive() && classtype.isPrimitive()) { + if (classtype == int.class) { + rs = Integer.decode(rs.toString()); + } else if (classtype == long.class) { + rs = Long.decode(rs.toString()); + } else if (classtype == short.class) { + rs = Short.decode(rs.toString()); + } else if (classtype == boolean.class) { + rs = "true".equalsIgnoreCase(rs.toString()); + } else if (classtype == byte.class) { + rs = Byte.decode(rs.toString()); + } else if (classtype == float.class) { + rs = Float.parseFloat(rs.toString()); + } else if (classtype == double.class) { + rs = Double.parseDouble(rs.toString()); + } + } + try { + element.field.set(dest, rs); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + } + + private static class ResourceElement { + + public final WeakReference dest; + + public final Field field; + + public final Class fieldType; + + public ResourceElement(T dest, Field field) { + this.dest = new WeakReference(dest); + this.field = field; + this.fieldType = field.getType(); + } + } + public static interface ResourceLoader { public Object load(ResourceFactory factory, Object src, String resourceName, Field field, Object attachment);