net.jrouter.impl.Injector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jrouter Show documentation
Show all versions of jrouter Show documentation
jrouter是一个围绕对象方法基于责任链(拦截器)模式设计的开源轻量级Java容器。它专注于方法的映射、调用、拦截和结果处理,采用基于配置和注解的方式来抽取和收集程序中对象的方法(method)以用于路由映射,HTTP控制器,RPC,各种应用等。
/*
* Copyright (C) 2010-2111 [email protected]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package net.jrouter.impl;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import net.jrouter.util.ClassUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Bean注入工具类。
*/
public class Injector { //NOPMD ClassNamingConventions
/* 日志记录 */
private static final Logger LOG = LoggerFactory.getLogger(Injector.class);
/** 对象类型与其注入属性的映射 */
static final Map CLASS_INJECTION = new HashMap<>();
/** action对象与其注入属性的映射 */
static final Map ACTION_INJECTION = new HashMap<>();
/**
* 所支持的属性转换对象类型
*/
private static final Set> SUPPORT_TYPES = new HashSet<>(18);
//初始化所支持的对象类型。
static {
//String to Class
SUPPORT_TYPES.add(Class.class);
SUPPORT_TYPES.add(String.class);
SUPPORT_TYPES.add(boolean.class);
SUPPORT_TYPES.add(Boolean.class);
SUPPORT_TYPES.add(byte.class);
SUPPORT_TYPES.add(Byte.class);
SUPPORT_TYPES.add(char.class);
SUPPORT_TYPES.add(Character.class);
SUPPORT_TYPES.add(double.class);
SUPPORT_TYPES.add(Double.class);
SUPPORT_TYPES.add(float.class);
SUPPORT_TYPES.add(Float.class);
SUPPORT_TYPES.add(int.class);
SUPPORT_TYPES.add(Integer.class);
SUPPORT_TYPES.add(long.class);
SUPPORT_TYPES.add(Long.class);
SUPPORT_TYPES.add(short.class);
SUPPORT_TYPES.add(Short.class);
}
/**
* private constructor
*/
private Injector() {
}
/**
* 添加指定对象类型与注入属性的映射。
*
* @param cls 指定的对象类型。
* @param properties 对象类型的属性映射集合。
*
* @return 如果已存在对象类型的属性则返回原有的属性集合,没有则返回 null。
*
* @throws IntrospectionException 如果在内省期间发生异常。
*/
public static Injection[] putClassProperties(Class> cls, Map properties) throws
IntrospectionException {
return CLASS_INJECTION.put(cls, convertToInjections(cls, properties));
}
/**
* 添加指定path的Action与注入属性的映射。
*
* @param cls 指定Action的类型。
* @param actionPath 指定Action的全路径。
* @param properties 对象类型的属性映射集合。
*
* @return 如果已存在Action的属性则返回原有的属性集合,没有则返回 null。
*
* @throws IntrospectionException 如果在内省期间发生异常。
*/
public static Injection[] putActionProperties(Class> cls, String actionPath, Map properties)
throws IntrospectionException {
return ACTION_INJECTION.put(actionPath, convertToInjections(cls, properties));
}
/**
* 转换指定对象类型的属性映射至注入对象集合。
*
* @param cls 指定的对象类型。
* @param properties 对象类型的属性映射集合。
*
* @return 注入对象集合。
*
* @throws IntrospectionException 如果在内省期间发生异常。
* @see Injection
*/
private static Injection[] convertToInjections(Class> cls, Map properties) throws
IntrospectionException {
//common class properties
Map supports = Injector.getSupportedProperties(cls);
List injections = new ArrayList<>(properties.size());
for (Map.Entry prop : properties.entrySet()) {
String pName = prop.getKey();
PropertyDescriptor pd = supports.get(pName);
if (pd == null) {
LOG.warn("Not supported property [{}] in [{}]", pName, cls);
} else {
Object value = prop.getValue();
if (value instanceof String) {
Object convertedValue = Injector.stringToObject((String) value, pd.getPropertyType());
if (convertedValue == null) {
LOG.warn("Not supported property [{}] for type [{}] in " + cls, pName, pd.getPropertyType());
} else {
injections.add(new Injection(pd.getWriteMethod(), convertedValue));
}
} else {
injections.add(new Injection(pd.getWriteMethod(), value));
}
}
}
return injections.toArray(new Injection[injections.size()]);
}
/*
* 注入Action所在路径(path)的属性;路径(path)属性已包含对象类型的属性。
*
* @param actionPath 指定Action的全路径。
* @param invoker Action所在的对象。
*
* @throws IllegalAccessException 如果属性注入的方法不可访问。
* @throws InvocationTargetException 如果属性注入的方法发生异常。
*/
static void injectAction(String actionPath, Object invoker) throws IllegalAccessException, InvocationTargetException {
Injection[] injects = ACTION_INJECTION.get(actionPath);
//如果指定的Action中无注入属性,则查找其对象类型的注入属性
// if (injects == null) {
// injects = classInjection.get(invoker.getClass());
// }
if (injects != null && injects.length > 0) {
for (Injection ij : injects) {
ij.setter.invoke(invoker, ij.value);
}
}
}
/**
* 注入指定对象的属性。
*
* @param obj 指定的对象。
*
* @throws IllegalAccessException 如果属性注入的方法不可访问。
* @throws InvocationTargetException 如果属性注入的方法发生异常。
*/
public static void injectObject(Object obj) throws IllegalAccessException, InvocationTargetException {
Injection[] injects = CLASS_INJECTION.get(obj.getClass());
if (injects != null && injects.length > 0) {
for (Injection ij : injects) {
ij.setter.invoke(obj, ij.value);
}
}
}
/**
* 清除类型与注入属性的映射。
*/
static void clear() {
CLASS_INJECTION.clear();
ACTION_INJECTION.clear();
}
/**
* 返回指定对象类型支持的属性描述映射。
*
* @param cls 指定的对象类型。
*
* @return 支持的属性描述映射。
*
* @throws IntrospectionException 如果在内省期间发生异常。
*/
public static Map getSupportedProperties(Class> cls) throws IntrospectionException {
PropertyDescriptor[] propds = Introspector.getBeanInfo(cls).getPropertyDescriptors();
Map support = new HashMap<>(propds.length);
//getPropertyDescriptors返回的PropertyDescriptor[]已经过滤了重复的属性名。
for (PropertyDescriptor p : propds) {
if (SUPPORT_TYPES.contains(p.getPropertyType())) {
support.put(p.getName(), p);
}
}
return support;
}
/**
* 注入指定对象的属性。
*
* @param obj 指定的对象。
* @param props 属性名称和字符串值的映射。
*
* @throws IntrospectionException 如果在内省期间发生异常。
* @throws IllegalAccessException 如果底层方法不可访问。
* @throws InvocationTargetException 如果底层方法抛出异常。
* @throws ClassNotFoundException 如果没有找到具有指定名称的类。
*/
// public static void setProperties(Object obj, Map props) throws
// IntrospectionException, IllegalAccessException, InvocationTargetException,
// ClassNotFoundException {
// PropertyDescriptor[] propds = Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors();
// for (PropertyDescriptor p : propds) {
// String value = props.get(p.getName());
// if (value != null) {
// Class type = p.getPropertyType();
// if (supportTypes.contains(type)) {
// p.getWriteMethod().invoke(obj, stringToObject(value, type));
// } else {
// //not supported setter method if been invoked
// LOG.error("Not supported set [{}] as [{}]", p.getName(), p.getPropertyType());
// }
// }
// }
// }
/**
* 转换字符串至指定类型的对象。
*
* @param str 指定的字符串。
* @param type 指定的类型。
*
* @return 转换后的对象。
*/
public static Object stringToObject(String str, Class> type) {
if (type == String.class) {
return str;
} else if (type == Class.class) {
try {
return ClassUtil.loadClass(str);
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(ex);
}
} else if (type == int.class || type == Integer.class) {
return Integer.parseInt(str);
} else if (type == boolean.class || type == Boolean.class) {
return Boolean.parseBoolean(str);
} else if (type == double.class || type == Double.class) {
return Double.parseDouble(str);
} else if (type == long.class || type == Long.class) {
return Long.parseLong(str);
} else if (type == float.class || type == Float.class) {
return Float.parseFloat(str);
} else if (type == byte.class || type == Byte.class) {
return Byte.parseByte(str);
} else if (type == char.class || type == Character.class) {
return str.charAt(0);
} else if (type == short.class || type == Short.class) {
return Short.parseShort(str);
}
return null;
}
/**
* 封装了Bean的setter方法和其值。
*/
public static class Injection {
/**
* 属性的setter方法
*/
private final Method setter;
/**
* 注入属性的值
*/
private final Object value;
/**
* 构造一个指定setter方法和属性值的对象。
*
* @param setter 属性的setter方法。
* @param value 属性的值。
*/
public Injection(Method setter, Object value) {
this.setter = setter;
this.value = value;
}
@Override
public String toString() {
return "Injection{" + "setter=" + setter.getName() + ", value=" + value + '}';
}
}
}