cn.featherfly.common.bean.BeanDescriptor Maven / Gradle / Ivy
The newest version!
package cn.featherfly.common.bean;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.collections4.map.ListOrderedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.featherfly.common.bean.matcher.BeanPropertyMatcher;
import cn.featherfly.common.lang.ClassUtils;
import cn.featherfly.common.lang.CollectionUtils;
import cn.featherfly.common.lang.LangUtils;
import cn.featherfly.common.lang.ServiceLoaderUtils;
/**
*
* java bean 的描述信息
*
*
* @author zhongj
* @param
* 描述的类型
*/
public class BeanDescriptor {
private static final Logger LOGGER = LoggerFactory.getLogger(BeanDescriptor.class);
private static final Map, BeanDescriptor>> BEAN_DESCRIPTORS
= new ConcurrentHashMap, BeanDescriptor>>();
private static final BeanPropertyFactory FACTORY = ServiceLoaderUtils.load(BeanPropertyFactory.class,
new ReflectionBeanPropertyFactory());
// private static BeanPropertyFactory factory = new
// ReflectionBeanPropertyFactory();
//
// static {
// ServiceLoader serviceLoader =
// ServiceLoader.load(BeanPropertyFactory.class);
// List factorys = new
// ArrayList();
// for (BeanPropertyFactory factory : serviceLoader) {
// factorys.add(factory);
// }
// if (factorys.size() > 1) {
// throw new IllegalArgumentException("找到多个BeanPropertyFactory实现 -> " +
// factorys) ;
// }
// if (factorys.isEmpty()) {
// factory = new ReflectionBeanPropertyFactory();
// } else {
// factory = factorys.get(0);
// }
// }
// private Map beanProperties = new HashMap(0);
private ListOrderedMap> beanProperties = new ListOrderedMap<>();
private Map typeGenericParams = new HashMap<>(0);
/**
* 句号(.)
*/
protected static final String DOT = ".";
/**
* @param type
* 类型
*/
protected BeanDescriptor(Class type) {
this.type = type;
initTypeGenericParam(this.type);
this.initFromField(this.type);
this.initFromMethod(this.type);
}
/**
*
* 初始化泛型参数
*
*
* @param type
* type
*/
protected void initTypeGenericParam(Class type) {
// 得到泛型父类
typeGenericParams = ClassUtils.getSuperClassGenricTypeMap(type);
}
// 从field开始初始化
private void initFromField(Class> parent) {
if (null == parent || parent == Object.class) {
return;
}
Field[] fields = parent.getDeclaredFields();
for (Field field : fields) {
Type genericType = typeGenericParams.get(field.getGenericType().toString());
Class> fieldType = null;
// 判断类型定义的泛型参数
if (genericType == null) {
fieldType = field.getType();
} else {
fieldType = (Class>) genericType;
}
Method getter = ClassUtils.getGetter(field, this.type);
Method setter = ClassUtils.getSetter(field, this.type);
if (getter != null || setter != null) {
BeanProperty> prop = FACTORY.create(field.getName(), field, fieldType, setter, getter, this.type,
field.getDeclaringClass());
beanProperties.put(prop.getName(), prop);
if (LOGGER.isTraceEnabled() && parent != this.type) {
LOGGER.trace("类{}从父类{}中继承的属性:[{}]",
new Object[] {this.type.getName(), parent.getName(), prop.getName()});
}
}
}
// 到父类中查找属性
initFromField(parent.getSuperclass());
}
// 初始化动态set get方法
private void initFromMethod(Class> type) {
Map> properties = new HashMap<>();
for (Method method : type.getMethods()) {
// 忽略Object对象
if (method.getDeclaringClass() == Object.class) {
continue;
}
if (ClassUtils.isGetter(method)) {
String propertyName = ClassUtils.getPropertyName(method);
if (!hasBeanProperty(propertyName)) {
Map prop = getProperty(properties, propertyName);
prop.put("get", method);
prop.put("ownerType", type);
// 因为先使用field初始化了,所以现在都应该只剩动态getter或动态setter了
/*
* try { Field field = ClassUtils
* .getField(method.getDeclaringClass(), propertyName);
* prop.put("field", field); if (field.getType() ==
* method.getReturnType()) { prop.put("get", method); } else
* { prop.put("get", method); } } catch
* (NoSuchFieldException e) { LOGGER.debug(e.getMessage());
* }
*/
}
}
if (ClassUtils.isSetter(method)) {
String propertyName = ClassUtils.getPropertyName(method);
if (!hasBeanProperty(propertyName)) {
Map prop = getProperty(properties, propertyName);
prop.put("set", method);
prop.put("ownerType", type);
}
// 因为先使用field初始化了,所以现在都应该只剩动态getter或动态setter了
/*
* if (prop.get("field") == null) { try { Field field =
* ClassUtils.getField(method.getDeclaringClass(),
* propertyName); prop.put("field", field); } catch
* (NoSuchFieldException e) { LOGGER.debug(e.getMessage()); } }
*/
}
}
for (Map prop : properties.values()) {
Class> propertyType = null;
Class> declaringType = null;
String propertyName = null;
// Field field = null;
Method setter = null;
Method getter = null;
/*
* if (prop.get("field") != null) { field = (Field)
* prop.get("field"); declaringType = field.getDeclaringClass();
* propertyName = field.getName(); propertyType =
* getGenericType(field.getGenericType(), field.getType()); }
*/
if (prop.get("get") != null) {
getter = (Method) prop.get("get");
declaringType = LangUtils.pick(declaringType, getter.getDeclaringClass());
propertyType = LangUtils.pick(propertyType,
getGenericType(getter.getGenericReturnType(), getter.getReturnType()));
propertyName = LangUtils.pick(propertyName, ClassUtils.getPropertyName(getter));
}
if (prop.get("set") != null) {
setter = (Method) prop.get("set");
declaringType = LangUtils.pick(declaringType, setter.getDeclaringClass());
propertyType = LangUtils.pick(propertyType,
getGenericType(setter.getGenericParameterTypes()[0], setter.getParameterTypes()[0]));
propertyName = LangUtils.pick(propertyName, ClassUtils.getPropertyName(setter));
}
BeanProperty> property = FACTORY.create(propertyName, null, propertyType, setter, getter, type,
declaringType);
beanProperties.put(property.getName(), property);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("类{}的属性:[{}], 定义子类{}", new Object[] {property.getOwnerType().getName(), property.getName(),
property.getDeclaringType().getName()});
}
}
}
private Class> getGenericType(Type genericTypeDeclaring, Class> genericType) {
Type gt = typeGenericParams.get(genericTypeDeclaring.toString());
// 判断类型定义的泛型参数
if (gt == null) {
return genericType;
} else {
return (Class>) gt;
}
}
private Map getProperty(Map> properties, String propertyName) {
Map prop = properties.get(propertyName);
if (prop == null) {
prop = new HashMap<>();
properties.put(propertyName, prop);
}
return prop;
}
/**
* @return 返回beanProperties
*/
public Collection> getBeanProperties() {
return beanProperties.values();
}
/**
*
* 返回指定索引属性.
*
*
* @param index
* 索引
* @return 指定属性
*/
public BeanProperty> getBeanProperty(int index) {
return beanProperties.getValue(index);
}
/**
*
* 返回指定属性. 如果没有则抛出NoSuchPropertyException异常
*
*
* @param name
* 属性名
* @return 指定属性
*/
public BeanProperty> getBeanProperty(String name) {
BeanProperty> property = beanProperties.get(name);
if (property == null) {
throw new NoSuchPropertyException(type, name);
}
return property;
}
/**
*
* 返回指定属性是否存在
*
*
* @param name
* 属性名
* @return 指定属性是否存在
*/
public boolean hasBeanProperty(String name) {
return beanProperties.get(name) != null;
}
/**
*
* 返回指定子孙属性. 如果没有则抛出NoSuchPropertyException异常
*
*
* @param name
* 属性名
* @return 指定属性
*/
public BeanProperty> getChildBeanProperty(String name) {
if (name.contains(DOT)) {
String currentPropertyName = name.substring(0, name.indexOf(DOT));
String innerPropertyName = name.substring(name.indexOf(DOT) + 1);
BeanProperty> property = getBeanProperty(currentPropertyName);
BeanDescriptor> propertyDescriptor = getBeanDescriptor(property.getType());
return propertyDescriptor.getChildBeanProperty(innerPropertyName);
} else {
return getBeanProperty(name);
}
}
/**
*
* 查找并返回第一个符合条件BeanProperty. 如果没有则返回null.
*
*
* @param condition
* 条件判断
* @return 第一个符合条件BeanProperty
*/
public BeanProperty> findBeanProperty(BeanPropertyMatcher condition) {
for (BeanProperty> beanProperty : getBeanProperties()) {
if (condition.match(beanProperty)) {
return beanProperty;
}
}
return null;
}
/**
*
* 查找并返回所有符合条件BeanProperty的集合. 如果没有则返回一个长度为0的集合.
*
*
* @param condition
* 条件判断
* @return 所有符合条件BeanProperty的集合
*/
public Collection> findBeanPropertys(BeanPropertyMatcher condition) {
Collection> coll = new ArrayList<>();
for (BeanProperty> beanProperty : getBeanProperties()) {
if (condition.match(beanProperty)) {
coll.add(beanProperty);
}
}
return coll;
}
/**
*
* 设置属性
*
*
* @param obj
* 目标对象
* @param name
* 属性名称
* @param value
* 属性值
*/
@SuppressWarnings("unchecked")
public void setProperty(T obj, String name, Object value) {
if (name.contains(DOT)) {
String currentPropertyName = name.substring(0, name.indexOf(DOT));
String innerPropertyName = name.substring(name.indexOf(DOT) + 1);
BeanProperty> property = getBeanProperty(currentPropertyName);
Object propertyValue = property.getValue(obj);
@SuppressWarnings("rawtypes")
BeanDescriptor propertyDescriptor = null;
// 中间层次为空,使用默认构造函数生成一个空对象
if (propertyValue == null) {
propertyDescriptor = getBeanDescriptor(property.getType());
try {
if (ClassUtils.isCellection(property.getType())) {
LOGGER.trace("类{}的属性[{}]为空,对象为Collection接口实现类,自动创建该属性对象",
new Object[] {property.getOwnerType().getName(), property.getName()});
propertyValue = CollectionUtils.newInstance(property.getType());
} else if (ClassUtils.isMap(property.getType())) {
LOGGER.trace("类{}的属性[{}]为空,对象为MAP接口,自动创建该属性对象",
new Object[] {property.getOwnerType().getName(), property.getName()});
propertyValue = CollectionUtils.newMap(property.getType());
} else {
LOGGER.trace("类{}的属性[{}]为空,自动创建该属性对象[使用newInstance()]",
new Object[] {property.getOwnerType().getName(), property.getName()});
propertyValue = property.getType().newInstance();
}
property.setValue(obj, propertyValue);
} catch (Exception e) {
throw new IllegalArgumentException(String.format("类%s缺少没有参数的构造函数", property.getType().getName()),
e);
}
} else {
propertyDescriptor = getBeanDescriptor(propertyValue.getClass());
}
propertyDescriptor.setProperty(propertyValue, innerPropertyName, value);
} else {
BeanProperty> p = getBeanProperty(name);
p.setValue(obj, value);
}
}
/**
*
* 添加属性值(如果添加目标是Collection,则会一直添加,如果是其他类型同setProperty)
*
*
* @param obj
* 对象
* @param name
* 属性名
* @param value
* 属性值
*/
public void addProperty(T obj, String name, Object value) {
BeanProperty> beanProperty = getChildBeanProperty(name);
if (ClassUtils.isCellection(beanProperty.getType())) {
@SuppressWarnings("unchecked")
Collection