mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add DynabeanValueProvider
This commit is contained in:
parent
a5624e6f94
commit
5aa10c06ee
@ -6,7 +6,6 @@ import cn.hutool.core.util.ClassUtil;
|
|||||||
import cn.hutool.core.util.ReflectUtil;
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,7 +15,7 @@ import java.util.Map;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
* @since 3.0.7
|
* @since 3.0.7
|
||||||
*/
|
*/
|
||||||
public class DynaBean extends CloneSupport<DynaBean> implements Serializable{
|
public class DynaBean extends CloneSupport<DynaBean> implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final Class<?> beanClass;
|
private final Class<?> beanClass;
|
||||||
@ -24,40 +23,46 @@ public class DynaBean extends CloneSupport<DynaBean> implements Serializable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建一个{@link DynaBean}
|
* 创建一个{@link DynaBean}
|
||||||
|
*
|
||||||
* @param bean 普通Bean
|
* @param bean 普通Bean
|
||||||
* @return {@link DynaBean}
|
* @return {@link DynaBean}
|
||||||
*/
|
*/
|
||||||
public static DynaBean create(Object bean){
|
public static DynaBean create(Object bean) {
|
||||||
return new DynaBean(bean);
|
return new DynaBean(bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建一个{@link DynaBean}
|
* 创建一个{@link DynaBean}
|
||||||
|
*
|
||||||
* @param beanClass Bean类
|
* @param beanClass Bean类
|
||||||
* @param params 构造Bean所需要的参数
|
* @param params 构造Bean所需要的参数
|
||||||
* @return {@link DynaBean}
|
* @return {@link DynaBean}
|
||||||
*/
|
*/
|
||||||
public static DynaBean create(Class<?> beanClass, Object... params){
|
public static DynaBean create(Class<?> beanClass, Object... params) {
|
||||||
return new DynaBean(beanClass, params);
|
return new DynaBean(beanClass, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------ Constructor start
|
//------------------------------------------------------------------------ Constructor start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
* @param beanClass Bean类
|
* @param beanClass Bean类
|
||||||
* @param params 构造Bean所需要的参数
|
* @param params 构造Bean所需要的参数
|
||||||
*/
|
*/
|
||||||
public DynaBean(Class<?> beanClass, Object... params){
|
public DynaBean(Class<?> beanClass, Object... params) {
|
||||||
this(ReflectUtil.newInstance(beanClass, params));
|
this(ReflectUtil.newInstance(beanClass, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
* @param bean 原始Bean
|
* @param bean 原始Bean
|
||||||
*/
|
*/
|
||||||
public DynaBean(Object bean){
|
public DynaBean(Object bean) {
|
||||||
Assert.notNull(bean);
|
Assert.notNull(bean);
|
||||||
if(bean instanceof DynaBean){
|
if (bean instanceof DynaBean) {
|
||||||
bean = ((DynaBean)bean).getBean();
|
bean = ((DynaBean) bean).getBean();
|
||||||
}
|
}
|
||||||
this.bean = bean;
|
this.bean = bean;
|
||||||
this.beanClass = ClassUtil.getClass(bean);
|
this.beanClass = ClassUtil.getClass(bean);
|
||||||
@ -66,37 +71,45 @@ public class DynaBean extends CloneSupport<DynaBean> implements Serializable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得字段对应值
|
* 获得字段对应值
|
||||||
* @param <T> 属性值类型
|
*
|
||||||
|
* @param <T> 属性值类型
|
||||||
* @param fieldName 字段名
|
* @param fieldName 字段名
|
||||||
* @return 字段值
|
* @return 字段值
|
||||||
* @throws BeanException 反射获取属性值或字段值导致的异常
|
* @throws BeanException 反射获取属性值或字段值导致的异常
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T get(String fieldName) throws BeanException{
|
public <T> T get(String fieldName) throws BeanException {
|
||||||
if(Map.class.isAssignableFrom(beanClass)){
|
if (Map.class.isAssignableFrom(beanClass)) {
|
||||||
return (T) ((Map<?, ?>)bean).get(fieldName);
|
return (T) ((Map<?, ?>) bean).get(fieldName);
|
||||||
}else{
|
} else {
|
||||||
try {
|
final BeanDesc.PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
|
||||||
final Method method = BeanUtil.getBeanDesc(beanClass).getGetter(fieldName);
|
if(null == prop){
|
||||||
if(null == method){
|
throw new BeanException("No public field or get method for {}", fieldName);
|
||||||
throw new BeanException("No get method for {}", fieldName);
|
|
||||||
}
|
|
||||||
return (T) method.invoke(this.bean);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new BeanException(e);
|
|
||||||
}
|
}
|
||||||
|
return (T) prop.getValue(bean);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否有指定名称的bean属性
|
||||||
|
*
|
||||||
|
* @param fieldName 字段名
|
||||||
|
* @return 是否有bean属性
|
||||||
|
* @since 5.4.2
|
||||||
|
*/
|
||||||
|
public boolean containsProp(String fieldName){
|
||||||
|
return null != BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得字段对应值,获取异常返回{@code null}
|
* 获得字段对应值,获取异常返回{@code null}
|
||||||
*
|
*
|
||||||
* @param <T> 属性值类型
|
* @param <T> 属性值类型
|
||||||
* @param fieldName 字段名
|
* @param fieldName 字段名
|
||||||
* @return 字段值
|
* @return 字段值
|
||||||
* @since 3.1.1
|
* @since 3.1.1
|
||||||
*/
|
*/
|
||||||
public <T> T safeGet(String fieldName){
|
public <T> T safeGet(String fieldName) {
|
||||||
try {
|
try {
|
||||||
return get(fieldName);
|
return get(fieldName);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -106,54 +119,54 @@ public class DynaBean extends CloneSupport<DynaBean> implements Serializable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置字段值
|
* 设置字段值
|
||||||
|
*
|
||||||
* @param fieldName 字段名
|
* @param fieldName 字段名
|
||||||
* @param value 字段值
|
* @param value 字段值
|
||||||
* @throws BeanException 反射获取属性值或字段值导致的异常
|
* @throws BeanException 反射获取属性值或字段值导致的异常
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
public void set(String fieldName, Object value) throws BeanException{
|
public void set(String fieldName, Object value) throws BeanException {
|
||||||
if(Map.class.isAssignableFrom(beanClass)){
|
if (Map.class.isAssignableFrom(beanClass)) {
|
||||||
((Map)bean).put(fieldName, value);
|
((Map) bean).put(fieldName, value);
|
||||||
}else{
|
} else {
|
||||||
try {
|
final BeanDesc.PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
|
||||||
final Method setter = BeanUtil.getBeanDesc(beanClass).getSetter(fieldName);
|
if(null == prop){
|
||||||
if(null == setter){
|
throw new BeanException("No public field or set method for {}", fieldName);
|
||||||
throw new BeanException("No set method for {}", fieldName);
|
|
||||||
}
|
|
||||||
setter.invoke(this.bean, value);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new BeanException(e);
|
|
||||||
}
|
}
|
||||||
|
prop.setValue(bean, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行原始Bean中的方法
|
* 执行原始Bean中的方法
|
||||||
|
*
|
||||||
* @param methodName 方法名
|
* @param methodName 方法名
|
||||||
* @param params 参数
|
* @param params 参数
|
||||||
* @return 执行结果,可能为null
|
* @return 执行结果,可能为null
|
||||||
*/
|
*/
|
||||||
public Object invoke(String methodName, Object... params){
|
public Object invoke(String methodName, Object... params) {
|
||||||
return ReflectUtil.invoke(this.bean, methodName, params);
|
return ReflectUtil.invoke(this.bean, methodName, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得原始Bean
|
* 获得原始Bean
|
||||||
|
*
|
||||||
* @param <T> Bean类型
|
* @param <T> Bean类型
|
||||||
* @return bean
|
* @return bean
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T getBean(){
|
public <T> T getBean() {
|
||||||
return (T)this.bean;
|
return (T) this.bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得Bean的类型
|
* 获得Bean的类型
|
||||||
|
*
|
||||||
* @param <T> Bean类型
|
* @param <T> Bean类型
|
||||||
* @return Bean类型
|
* @return Bean类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> Class<T> getBeanClass(){
|
public <T> Class<T> getBeanClass() {
|
||||||
return (Class<T>) this.beanClass;
|
return (Class<T>) this.beanClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@ package cn.hutool.core.bean.copier;
|
|||||||
import cn.hutool.core.bean.BeanDesc.PropDesc;
|
import cn.hutool.core.bean.BeanDesc.PropDesc;
|
||||||
import cn.hutool.core.bean.BeanException;
|
import cn.hutool.core.bean.BeanException;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.bean.DynaBean;
|
||||||
import cn.hutool.core.bean.copier.provider.BeanValueProvider;
|
import cn.hutool.core.bean.copier.provider.BeanValueProvider;
|
||||||
|
import cn.hutool.core.bean.copier.provider.DynaBeanValueProvider;
|
||||||
import cn.hutool.core.bean.copier.provider.MapValueProvider;
|
import cn.hutool.core.bean.copier.provider.MapValueProvider;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.copier.Copier;
|
import cn.hutool.core.lang.copier.Copier;
|
||||||
@ -97,6 +99,9 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
|||||||
if (this.source instanceof ValueProvider) {
|
if (this.source instanceof ValueProvider) {
|
||||||
// 目标只支持Bean
|
// 目标只支持Bean
|
||||||
valueProviderToBean((ValueProvider<String>) this.source, this.dest);
|
valueProviderToBean((ValueProvider<String>) this.source, this.dest);
|
||||||
|
} else if (this.source instanceof DynaBean) {
|
||||||
|
// 目标只支持Bean
|
||||||
|
valueProviderToBean(new DynaBeanValueProvider((DynaBean) this.source, copyOptions.ignoreError), this.dest);
|
||||||
} else if (this.source instanceof Map) {
|
} else if (this.source instanceof Map) {
|
||||||
if (this.dest instanceof Map) {
|
if (this.dest instanceof Map) {
|
||||||
mapToMap((Map<?, ?>) this.source, (Map<?, ?>) this.dest);
|
mapToMap((Map<?, ?>) this.source, (Map<?, ?>) this.dest);
|
||||||
|
@ -12,7 +12,6 @@ import java.util.Map;
|
|||||||
* Bean的值提供者
|
* Bean的值提供者
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class BeanValueProvider implements ValueProvider<String> {
|
public class BeanValueProvider implements ValueProvider<String> {
|
||||||
|
|
||||||
@ -23,8 +22,8 @@ public class BeanValueProvider implements ValueProvider<String> {
|
|||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param bean Bean
|
* @param bean Bean
|
||||||
* @param ignoreCase 是否忽略字段大小写
|
* @param ignoreCase 是否忽略字段大小写
|
||||||
* @param ignoreError 是否忽略字段值读取错误
|
* @param ignoreError 是否忽略字段值读取错误
|
||||||
*/
|
*/
|
||||||
public BeanValueProvider(Object bean, boolean ignoreCase, boolean ignoreError) {
|
public BeanValueProvider(Object bean, boolean ignoreCase, boolean ignoreError) {
|
||||||
@ -35,11 +34,7 @@ public class BeanValueProvider implements ValueProvider<String> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object value(String key, Type valueType) {
|
public Object value(String key, Type valueType) {
|
||||||
PropDesc sourcePd = sourcePdMap.get(key);
|
final PropDesc sourcePd = getPropDesc(key, valueType);
|
||||||
if(null == sourcePd && (Boolean.class == valueType || boolean.class == valueType)) {
|
|
||||||
//boolean类型字段字段名支持两种方式
|
|
||||||
sourcePd = sourcePdMap.get(StrUtil.upperFirstAndAddPre(key, "is"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Object result = null;
|
Object result = null;
|
||||||
if (null != sourcePd) {
|
if (null != sourcePd) {
|
||||||
@ -50,7 +45,7 @@ public class BeanValueProvider implements ValueProvider<String> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsKey(String key) {
|
public boolean containsKey(String key) {
|
||||||
PropDesc sourcePd = getPropDesc(key);
|
final PropDesc sourcePd = getPropDesc(key, null);
|
||||||
|
|
||||||
// 字段描述不存在或忽略读的情况下,表示不存在
|
// 字段描述不存在或忽略读的情况下,表示不存在
|
||||||
return null != sourcePd && false == sourcePd.isIgnoreGet();
|
return null != sourcePd && false == sourcePd.isIgnoreGet();
|
||||||
@ -59,12 +54,13 @@ public class BeanValueProvider implements ValueProvider<String> {
|
|||||||
/**
|
/**
|
||||||
* 获得属性描述
|
* 获得属性描述
|
||||||
*
|
*
|
||||||
* @param key 字段名
|
* @param key 字段名
|
||||||
|
* @param valueType 值类型,用于判断是否为Boolean,可以为null
|
||||||
* @return 属性描述
|
* @return 属性描述
|
||||||
*/
|
*/
|
||||||
private PropDesc getPropDesc(String key){
|
private PropDesc getPropDesc(String key, Type valueType) {
|
||||||
PropDesc sourcePd = sourcePdMap.get(key);
|
PropDesc sourcePd = sourcePdMap.get(key);
|
||||||
if(null == sourcePd) {
|
if (null == sourcePd && (null == valueType || Boolean.class == valueType || boolean.class == valueType)) {
|
||||||
//boolean类型字段字段名支持两种方式
|
//boolean类型字段字段名支持两种方式
|
||||||
sourcePd = sourcePdMap.get(StrUtil.upperFirstAndAddPre(key, "is"));
|
sourcePd = sourcePdMap.get(StrUtil.upperFirstAndAddPre(key, "is"));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package cn.hutool.core.bean.copier.provider;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.DynaBean;
|
||||||
|
import cn.hutool.core.bean.copier.ValueProvider;
|
||||||
|
import cn.hutool.core.convert.Convert;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DynaBean值提供者
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 5.4.2
|
||||||
|
*/
|
||||||
|
public class DynaBeanValueProvider implements ValueProvider<String> {
|
||||||
|
|
||||||
|
private final DynaBean dynaBean;
|
||||||
|
private final boolean ignoreError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param dynaBean DynaBean
|
||||||
|
* @param ignoreError 是否忽略错误
|
||||||
|
*/
|
||||||
|
public DynaBeanValueProvider(DynaBean dynaBean, boolean ignoreError) {
|
||||||
|
this.dynaBean = dynaBean;
|
||||||
|
this.ignoreError = ignoreError;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object value(String key, Type valueType) {
|
||||||
|
final Object value = dynaBean.get(key);
|
||||||
|
return Convert.convertWithCheck(valueType, value, null, this.ignoreError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(String key) {
|
||||||
|
return dynaBean.containsProp(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user