org.redkale.util.ResourceFactory Maven / Gradle / Ivy
/*
* 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.ref.WeakReference;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.logging.*;
import javax.annotation.Resource;
/**
*
* 依赖注入功能主类
*
* 如果@Resource(name = "$") 表示资源name采用所属对象的name
* 如果没有@Resource且对象实现了Resourcable, 则会取对象的resourceName()方法值
*
* name规则:
* 1: "$"有特殊含义, 不能表示"$"资源本身
* 2: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
*
*
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@SuppressWarnings("unchecked")
public final class ResourceFactory {
public static final String RESOURCE_PARENT_NAME = "$";
private static final Logger logger = Logger.getLogger(ResourceFactory.class.getSimpleName());
private final ResourceFactory parent;
private static final ResourceFactory instance = new ResourceFactory(null);
private final List> chidren = new CopyOnWriteArrayList<>();
private final ConcurrentHashMap loadermap = new ConcurrentHashMap();
private final ConcurrentHashMap> store = new ConcurrentHashMap();
private ResourceFactory(ResourceFactory parent) {
this.parent = parent;
}
/**
* 获取根ResourceFactory
*
* @return ResourceFactory
*/
public static ResourceFactory root() {
return instance;
}
/**
* 创建ResourceFactory子节点
*
* @return ResourceFactory
*/
public ResourceFactory createChild() {
ResourceFactory child = new ResourceFactory(this);
this.chidren.add(new WeakReference<>(child));
return child;
}
/**
* 获取所有ResourceFactory子节点
*
* @return List
*/
public List getChildren() {
List result = new ArrayList<>();
for (WeakReference ref : chidren) {
ResourceFactory rf = ref.get();
if (rf != null) result.add(rf);
}
return result;
}
/**
* 清空当前ResourceFactory注入资源
*
*/
public void release() {
this.store.clear();
}
/**
* 检查资源名是否合法
*
* name规则:
* 1: "$"有特殊含义, 表示资源本身,"$"不能单独使用
* 2: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
*
*
* @param name String
*/
public static void checkResourceName(String name) {
if (name == null || (!name.isEmpty() && !name.matches("^[a-zA-Z0-9_;\\-\\.\\[\\]\\(\\)]+$"))) {
throw new IllegalArgumentException("name(" + name + ") contains illegal character, must be (a-z,A-Z,0-9,_,.,(,),-,[,])");
}
}
/**
* 将对象指定类型且name=""注入到资源池中,并同步已被注入的资源
*
* @param 泛型
* @param clazz 资源类型
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final Class clazz, final A rs) {
return register(true, clazz, rs);
}
/**
* 将对象指定类型且name=""注入到资源池中
*
* @param 泛型
* @param autoSync 是否同步已被注入的资源
* @param clazz 资源类型
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final boolean autoSync, final Class clazz, final A rs) {
return register(autoSync, "", clazz, rs);
}
/**
* 将对象以name=""注入到资源池中,并同步已被注入的资源
*
* @param 泛型
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final A rs) {
return register(true, rs);
}
/**
* 将对象以name=""注入到资源池中,并同步已被注入的资源
*
* @param 泛型
* @param autoSync 是否同步已被注入的资源
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final boolean autoSync, final A rs) {
if (rs == null) return null;
return (A) register(autoSync, "", rs);
}
/**
* 将boolean对象以指定资源名注入到资源池中,并同步已被注入的资源
*
* @param name 资源名
* @param value 资源值
*
*/
public void register(final String name, final boolean value) {
register(true, name, boolean.class, value);
}
/**
* 将boolean对象以指定资源名注入到资源池中
*
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param value 资源值
*
*/
public void register(final boolean autoSync, final String name, final boolean value) {
register(autoSync, name, boolean.class, value);
}
/**
* 将byte对象以指定资源名注入到资源池中,并同步已被注入的资源
*
* @param name 资源名
* @param value 资源值
*
*/
public void register(final String name, final byte value) {
register(true, name, byte.class, value);
}
/**
* 将byte对象以指定资源名注入到资源池中
*
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param value 资源值
*
*/
public void register(final boolean autoSync, final String name, final byte value) {
register(autoSync, name, byte.class, value);
}
/**
* 将short对象以指定资源名注入到资源池中,并同步已被注入的资源
*
* @param name 资源名
* @param value 资源值
*
*/
public void register(final String name, final short value) {
register(true, name, short.class, value);
}
/**
* 将short对象以指定资源名注入到资源池中
*
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param value 资源值
*
*/
public void register(final boolean autoSync, final String name, final short value) {
register(autoSync, name, short.class, value);
}
/**
* 将int对象以指定资源名注入到资源池中,并同步已被注入的资源
*
* @param name 资源名
* @param value 资源值
*
*/
public void register(final String name, final int value) {
register(true, name, int.class, value);
}
/**
* 将int对象以指定资源名注入到资源池中
*
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param value 资源值
*
*/
public void register(final boolean autoSync, final String name, final int value) {
register(autoSync, name, int.class, value);
}
/**
* 将float对象以指定资源名注入到资源池中,并同步已被注入的资源
*
* @param name 资源名
* @param value 资源值
*
*/
public void register(final String name, final float value) {
register(true, name, float.class, value);
}
/**
* 将float对象以指定资源名注入到资源池中
*
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param value 资源值
*
*/
public void register(final boolean autoSync, final String name, final float value) {
register(autoSync, name, float.class, value);
}
/**
* 将long对象以指定资源名注入到资源池中,并同步已被注入的资源
*
* @param name 资源名
* @param value 资源值
*
*/
public void register(final String name, final long value) {
register(true, name, long.class, value);
}
/**
* 将long对象以指定资源名注入到资源池中
*
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param value 资源值
*
*/
public void register(final boolean autoSync, final String name, final long value) {
register(autoSync, name, long.class, value);
}
/**
* 将double对象以指定资源名注入到资源池中,并同步已被注入的资源
*
* @param name 资源名
* @param value 资源值
*
*/
public void register(final String name, final double value) {
register(true, name, double.class, value);
}
/**
* 将double对象以指定资源名注入到资源池中
*
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param value 资源值
*
*/
public void register(final boolean autoSync, final String name, final double value) {
register(autoSync, name, double.class, value);
}
/**
* 将对象以指定资源名注入到资源池中,并同步已被注入的资源
*
* @param 泛型
* @param name 资源名
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final String name, final A rs) {
return register(true, name, rs);
}
/**
* 将对象以指定资源名注入到资源池中
*
* @param 泛型
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final boolean autoSync, final String name, final A rs) {
checkResourceName(name);
final Class claz = rs.getClass();
ResourceType rtype = claz.getAnnotation(ResourceType.class);
if (rtype == null) {
return (A) register(autoSync, name, claz, rs);
} else {
A old = null;
A t = (A) register(autoSync, name, rtype.value(), rs);
if (t != null) old = t;
return old;
}
}
/**
* 将对象以指定资源名和类型注入到资源池中,并同步已被注入的资源
*
* @param 泛型
* @param name 资源名
* @param clazz 资源类型
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final String name, final Class clazz, final A rs) {
return register(true, name, clazz, rs);
}
/**
* 将对象以指定资源名和类型注入到资源池中,并同步已被注入的资源
*
* @param 泛型
* @param name 资源名
* @param clazz 资源类型
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final String name, final Type clazz, final A rs) {
return register(true, name, clazz, rs);
}
/**
* 将对象以指定资源名和类型注入到资源池中
*
* @param 泛型
* @param autoSync 是否同步已被注入的资源
* @param name 资源名
* @param clazz 资源类型
* @param rs 资源对象
*
* @return 旧资源对象
*/
public A register(final boolean autoSync, final String name, final Type clazz, final A rs) {
checkResourceName(name);
ConcurrentHashMap 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);
}
}
}
ResourceEntry re = map.get(name);
if (re == null) {
map.put(name, new ResourceEntry(rs));
} else {
map.put(name, new ResourceEntry(rs, name, re.elements, autoSync));
}
return re == null ? null : (A) re.value;
}
/**
* 判断是否包含指定资源名和资源类型的资源对象
*
* @param 泛型
* @param recursive 是否遍历父节点
* @param name 资源名
* @param clazz 资源类型
*
* @return 是否存在
*/
public boolean contains(boolean recursive, String name, Class clazz) {
Map map = this.store.get(clazz);
return map == null ? ((recursive && parent != null) ? parent.contains(recursive, name, clazz) : false) : map.containsKey(name);
}
/**
* 查找指定资源名和资源类型的资源对象所在的ResourceFactory, 没有则返回null
*
* @param name 资源名
* @param clazz 资源类型
*
* @return ResourceFactory
*/
public ResourceFactory findResourceFactory(String name, Type clazz) {
Map map = this.store.get(clazz);
if (map != null && map.containsKey(name)) return this;
if (parent != null) return parent.findResourceFactory(name, clazz);
return null;
}
public A find(Class clazz) {
return find("", clazz);
}
public A find(String name, Type clazz) {
ResourceEntry re = findEntry(name, clazz);
return re == null ? null : (A) re.value;
}
public A find(String name, Class clazz) {
ResourceEntry re = findEntry(name, clazz);
return re == null ? null : re.value;
}
public A findChild(final String name, final Class clazz) {
A rs = find(name, clazz);
if (rs != null) return rs;
for (Map.Entry> en : this.store.entrySet()) {
if (!(en.getKey() instanceof Class)) continue;
if (!clazz.isAssignableFrom((Class) en.getKey())) continue;
ResourceEntry v = en.getValue().get(name);
if (v != null) return (A) v.value;
}
return null;
}
private ResourceEntry findEntry(String name, Type clazz) {
Map map = this.store.get(clazz);
if (map != null) {
ResourceEntry re = map.get(name);
if (re != null) return re;
}
if (parent != null) return parent.findEntry(name, clazz);
return null;
}
public List query(Class clazz) {
return query(new ArrayList<>(), clazz);
}
public List query(Type clazz) {
return query(new ArrayList<>(), clazz);
}
private List query(final List list, Type clazz) {
Map map = this.store.get(clazz);
if (map != null) {
for (ResourceEntry re : map.values()) {
if (re.value != null) list.add((A) re.value);
}
}
if (parent != null) parent.query(list, clazz);
return list;
}
public List query(final BiPredicate predicate) {
return query(new ArrayList<>(), predicate);
}
private List query(final List list, final BiPredicate predicate) {
if (predicate == null) return list;
for (ConcurrentHashMap map : this.store.values()) {
for (Map.Entry en : map.entrySet()) {
if (predicate.test(en.getKey(), en.getValue().value)) {
list.add((A) en.getValue().value);
}
}
}
if (parent != null) parent.query(list, predicate);
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;
}
public boolean inject(final Object src) {
return inject(src, null);
}
public boolean inject(final Object src, final T attachment) {
return inject(src, attachment, null);
}
public boolean inject(final Object src, final BiConsumer