commons-beanutils

内省(了解)

内省的目标是得到JavaBean属性的读、写方法的反射对象,通过反射对JavaBean属性进行操作的一组API。例如User类有名为username的JavaBean属性,通过两个Method对象(一个是getUsenrmae(),一个是setUsername())来操作User对象。

如果你还不能理解内省是什么,那么我们通过一个问题来了解内省的作用。现在我们有一个Map,内容如下:

       Map<String,String> map = new HashMap<String,String>();

       map.put("username", "admin");

       map.put("password", "admin123");

public class User {

    private String username;

    private String password;

 

    public User(String username, String password) {

       this.username = username;

       this.password = password;

    }

    public User() {

    }

    public String getUsername() {

       return username;

    }

    public void setUsername(String username) {

       this.username = username;

    }

    public String getPassword() {

       return password;

    }

    public void setPassword(String password) {

       this.password = password;

    }

    public String toString() {

       return "User [username=" + username + ", password=" + password + "]";

    }

}

 

现在需要把map的数据封装到一个User对象中!User类有两个JavaBean属性,一个叫username,另一个叫password。

你可能想到的是反射,通过map的key来查找User类的Field!这么做是没有问题的,但我们要知道类的成员变量是私有的,虽然也可以通过反射去访问类的私有的成员变量,但我们也要清楚反射访问私有的东西是有“危险”的,所以还是建议通过getUsername和setUsername来访问JavaBean属性。

 

2.1 内省之获取BeanInfo

我们这里不想去对JavaBean规范做过多的介绍,所以也就不在多介绍BeanInfo的“出身”了。你只需要知道如何得到它,以及BeanInfo有什么。

通过java.beans.Introspector的getBeanInfo()方法来获取java.beans.BeanInfo实例。

BeanInfo beanInfo = Introspector.getBeanInfo(User.class);

 

2.2 得到所有属性描述符(PropertyDescriptor)

通过BeanInfo可以得到这个类的所有JavaBean属性的PropertyDescriptor对象。然后就可以通过PropertyDescriptor对象得到这个属性的getter/setter方法的Method对象了。

PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();

 

每个PropertyDescriptor对象对应一个JavaBean属性:

  1. String getName():获取JavaBean属性名称;
  2. Method getReadMethod:获取属性的读方法;
  3. Method getWriteMethod:获取属性的写方法。

 

2.3 完成Map数据封装到User对象中

    public void fun1() throws Exception {

       Map<String,String> map = new HashMap<String,String>();

       map.put("username", "admin");

       map.put("password", "admin123");

      

       BeanInfo beanInfo = Introspector.getBeanInfo(User.class);[崔1] 

      

       PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();[崔2] 

      

       User user = new User();[崔3] 

       for(PropertyDescriptor pd : pds)[崔4]  {

           String name = pd.getName();[崔5] 

           String value = map.get(name);[崔6] 

           if(value != null)[崔7]  {

              Method writeMethod = pd.getWriteMethod();[崔8] 

              writeMethod.invoke(user, value);[崔9] 

           }

       }

      

       System.out.println(user);

    }

 

3 commons-beanutils

提到内省,不能不提commons-beanutils这个工具。它底层使用了内省,对内省进行了大量的简化!

使用beanutils需要的jar包:

  1. commons-beanutils.jar;
  2. commons-logging.jar;

 

3.1 设置JavaBean属性

       User user = new User();

      

       BeanUtils.setProperty(user, "username", "admin");[崔10] 

       BeanUtils.setProperty(user, "password", "admin123");[崔11] 

      

       System.out.println(user);

 

3.2 获取JavaBean属性

       User user = new User("admin", "admin123");

      

       String username = BeanUtils.getProperty(user, "username");[崔12] 

       String password = BeanUtils.getProperty(user, "password");[崔13] 

      

       System.out.println("username=" + username + ", password=" + password);

 

3.3 封装Map数据到JavaBean对象中

       Map<String,String> map = new HashMap<String,String>();

       map.put("username", "admin");

       map.put("password", "admin123");

      

       User user = new User();

 

       BeanUtils.populate(user, map);[崔14] 

      

       System.out.println(user);


 工具类:将Map直接封装到Bean

public static <T> T toBean(Map map, Class<T> clazz) {
		try {
			/*
			 * 1. 创建指定类型的javabean对象
			 */
			T bean = clazz.newInstance();
			/*
			 * 2. 把数据封装到javabean中
			 */
			BeanUtils.populate(bean, map);
			/*
			 * 返回javabean对象
			 */
			return bean;
		} catch(Exception e) {
			throw new RuntimeException(e);
		}
	}

测试:

public class Demo1 {
	@Test
	public void fun1() throws Exception {
		String className = "cn.itcast.domain.Person";
		Class clazz = Class.forName(className);
		Object bean = clazz.newInstance();
		
		BeanUtils.setProperty(bean, "name", "张三");
		BeanUtils.setProperty(bean, "age", "23");
		BeanUtils.setProperty(bean, "gender", "男");
		BeanUtils.setProperty(bean, "xxx", "XXX");
		
		String age = BeanUtils.getProperty(bean, "age");
		System.out.println(age);
		System.out.println(bean);
	}
	
	/*
	 * 把map中的属性直接封装到一个bean中 
	 * 
	 * Map: {"username":"zhangSan", "password","123"}
	 * 我们要把map的数据封装到一个javabean中!要求map的key与bean的属性名相同!
	 */
	@Test
	public void fun2() throws Exception {
		Map<String,String> map = new HashMap<String,String>();
		map.put("username", "zhangSan");
		map.put("password", "123");
		
		User user = new User();
		BeanUtils.populate(user, map);
		
		System.out.println(user);
	}
	
	@Test
	public void fun3() {
		Map<String,String> map = new HashMap<String,String>();
		map.put("username", "zhangSan");
		map.put("password", "123");
		
		/*
		 * request.getParameterMap();
		 */
		
		User user = CommonUtils.toBean(map, User.class);
		System.out.println(user);
	}

commons-beanutils是Apache开源组织提供的用于操作JAVA BEAN的工具包。使用commons-beanutils,我们可以很方便的对bean对象的属性进行操作。今天为大家介绍一下该包的常用方法。

在介绍常用类之前,我们先来 编写一个用于测试的BEAN类:

package com.gujin.entity;

public class UserInfo
{
   private String userId;
   private String userName;

   public UserInfo()
   {
   }

   public UserInfo(String userId, String userName)
   {
      this.userId = userId;
      this.userName = userName;
   }

   public String getUserId()
   {
      return userId;
   }

   public void setUserId(String userId)
   {
      this.userId = userId;
   }

   public String getUserName()
   {
      return userName;
   }

   public void setUserName(String userName)
   {
      this.userName = userName;
   }

   @Override
   public String toString()
   {
      return String.format("{userId:%s,userName:%s}", userId, userName);
   }
}

MethodUtils

MethodUtils通过反射访问对象的方法并且执行方法。

方法摘要:

返回值 方法名 说明
static int clearCache() 清空方法缓存
static Method getAccessibleMethod(Class<?> clazz, Method method) 返回一个可访问的方法
static Method getAccessibleMethod(Class<?> clazz, String methodName, Class<?> parameterType) 返回一个可访问的方法
static Method getAccessibleMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes) 返回一个可访问的方法
static Method getAccessibleMethod(Method method) 返回一个可访问的方法
static Method getMatchingAccessibleMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes) 查找与方法名及参数匹配的可访问方法
static Class<?> getPrimitiveType(Class<?> wrapperType) 获得包装类的基本数据类型
static Class<?> getPrimitiveWrapper(Class<?> primitiveType) 获得基本数据类型的包装类型
static Object invokeExactMethod(Object object, String methodName, Object arg) 执行方法
static Object invokeExactMethod(Object object, String methodName, Object[] args) 执行方法
static Object invokeExactMethod(Object object, String methodName, Object[] args, Class<?>[] parameterTypes) 执行方法
static Object invokeExactStaticMethod(Class<?> objectClass, String methodName, Object arg) 执行静态方法
static Object invokeExactStaticMethod(Class<?> objectClass, String methodName, Object[] args) 执行静态方法
static Object invokeExactStaticMethod(Class<?> objectClass, String methodName, Object[] args, Class<?>[] parameterTypes) 执行静态方法
static Object invokeMethod(Object object, String methodName, Object arg) 执行方法
static Object invokeMethod(Object object, String methodName, Object[] args) 执行方法
static Object invokeMethod(Object object, String methodName, Object[] args, Class<?>[] parameterTypes) 执行方法
static Object invokeStaticMethod(Class<?> objectClass, String methodName, Object arg) 执行静态方法
static Object invokeStaticMethod(Class<?> objectClass, String methodName, Object[] args) 执行静态方法
static Object invokeStaticMethod(Class<?> objectClass, String methodName, Object[] args, Class<?>[] parameterTypes) 执行静态方法
static boolean isAssignmentCompatible(Class<?> parameterType, Class<?> parameterization) 确定是否可以使用一个类型作为方法调用参数
static void setCacheMethods(boolean cacheMethods) 设置缓存方法
static Class<?> toNonPrimitiveClass(Class<?> clazz) 如果是简单数据类型则返回对应的包装类,否则返回本身

使用示例:

package com.gujin.beanutils;

import java.lang.reflect.Method;

import org.apache.commons.beanutils.MethodUtils;
import org.junit.Test;

import com.gujin.entity.UserInfo;

public class MethodUtilsTest
{
   @Test
   public void test() throws Exception
   {
      UserInfo userInfo = new UserInfo();
      // 通过方法名和参数类型获得可访问方法
      Method method = MethodUtils.getAccessibleMethod(UserInfo.class,
            "setUserId", String.class);
      method.invoke(userInfo, "jianggujin");
      // 可以直接通过invokeMethod执行方法
      MethodUtils.invokeMethod(userInfo, "setUserName", "蒋固金");
      System.out.println(userInfo);
   }
}

运行结果:

{userId:jianggujin,userName:蒋固金}

ConstructorUtils

ConstructorUtils通过反射提供了构造方法相关的便捷操作方法。

方法摘要:

返回值 方法名 说明
static <T> Constructor<T> getAccessibleConstructor(Class<T> klass, Class<?> parameterType) 获得含有一个形参的构造方法
static <T> Constructor<T> getAccessibleConstructor(Class<T> klass, Class<?>[] parameterTypes) 获得含有指定类型形参的构造方法
static <T> Constructor<T> getAccessibleConstructor(Constructor<T> ctor) 获得可访问构造方法
static <T> T invokeConstructor(Class<T> klass, Object arg) 执行构造方法
static <T> T invokeConstructor(Class<T> klass, Object[] args) 执行构造方法
static <T> T invokeConstructor(Class<T> klass, Object[] args, Class<?>[] parameterTypes) 执行构造方法
static <T> T invokeExactConstructor(Class<T> klass, Object arg) 执行构造方法
static <T> T invokeExactConstructor(Class<T> klass, Object[] args) 执行构造方法
static <T> T invokeExactConstructor(Class<T> klass, Object[] args, Class<?>[] parameterTypes) 执行构造方法

使用示例:

package com.gujin.beanutils;

import java.lang.reflect.Constructor;

import org.apache.commons.beanutils.ConstructorUtils;
import org.junit.Test;

import com.gujin.entity.UserInfo;

public class ConstructorUtilsTest
{
   @Test
   public void test() throws Exception
   {
      Constructor<UserInfo> constructor = ConstructorUtils
            .getAccessibleConstructor(UserInfo.class, new Class[] {
                  String.class, String.class });
      System.out.println(constructor.newInstance("jianggujin", "蒋固金"));
      // 更简洁的写法
      UserInfo userInfo = ConstructorUtils.invokeConstructor(UserInfo.class,
            new String[] { "jianggujin", "蒋固金" });
      System.out.println(userInfo);
   }
}

运行结果:

{userId:jianggujin,userName:蒋固金} 
{userId:jianggujin,userName:蒋固金}

PropertyUtils

PropertyUtils通过反射提供了对象属性的便捷操作方法。

方法摘要:

返回值 方法名 说明
static void addBeanIntrospector(BeanIntrospector introspector) 添加一个BeanIntrospector
static void clearDescriptors() 清空所有属性描述信息
static void copyProperties(Object dest, Object orig) 复制属性
static Map<String,Object> describe(Object bean) 属性描述
static Object getIndexedProperty(Object bean, String name) 指定索引属性值
static Object getIndexedProperty(Object bean, String name, int index) 指定索引属性值
static Object getMappedProperty(Object bean, String name) 获得Map属性
static Object getMappedProperty(Object bean, String name, String key) 获得Map属性中指定键对应的值
static Object getNestedProperty(Object bean, String name) 获得嵌套属性
static Object getProperty(Object bean, String name) 获得属性
static PropertyDescriptor getPropertyDescriptor(Object bean, String name) 获得属性描述
static PropertyDescriptor[] getPropertyDescriptors(Class<?> beanClass) 获得属性描述
static PropertyDescriptor[] getPropertyDescriptors(Object bean) 获得属性描述
static Class<?> getPropertyType(Object bean, String name) 获得属性类型
static Method getReadMethod(PropertyDescriptor descriptor) 返回一个可访问的属性的getter方法
static Object getSimpleProperty(Object bean, String name) 返回属性值
static Method getWriteMethod(PropertyDescriptor descriptor) 返回一个可访问的属性的setter方法
static boolean isReadable(Object bean, String name) 判断是否为可读属性
static boolean isWriteable(Object bean, String name) 判断是否为可写属性
static boolean removeBeanIntrospector(BeanIntrospector introspector) 移除BeanIntrospector
static void resetBeanIntrospectors() 重置BeanIntrospector
static void setIndexedProperty(Object bean, String name, int index, Object value) 设置指定索引属性值
static void setIndexedProperty(Object bean, String name, Object value) 设置指定索引属性值
static void setMappedProperty(Object bean, String name, Object value) 设置Map属性的值
static void setMappedProperty(Object bean, String name, String key, Object value) 设置Map属性指定键的值
static void setNestedProperty(Object bean, String name, Object value) 设置嵌套属性的值
static void setProperty(Object bean, String name, Object value) 设置属性值
static void setSimpleProperty(Object bean, String name, Object value) 设置属性值

使用示例:

package com.gujin.beanutils;

import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Test;

import com.gujin.entity.UserInfo;

public class PropertyUtilsTest
{
   @Test
   public void test() throws Exception
   {
      UserInfo userInfo = new UserInfo("jianggujin", "蒋固金");
      UserInfo copyed = new UserInfo();
      PropertyUtils.copyProperties(copyed, userInfo);
      System.out.println(copyed);
      System.out.println(PropertyUtils.describe(userInfo));
      PropertyUtils.setProperty(userInfo, "userId", "gjjiang");
      System.out.println(userInfo);
   }
}

运行结果:

{userId:jianggujin,userName:蒋固金} 
{userId=jianggujin, class=class com.gujin.entity.UserInfo, userName=蒋固金} 
{userId:gjjiang,userName:蒋固金}

BeanUtils

BeanUtils通过反射提供了Bean对象的便捷操作方法。

方法摘要:

返回值 方法名 说明
static Object cloneBean(Object bean) 克隆对象
static void copyProperties(Object dest, Object orig) 复制属性
static void copyProperty(Object bean, String name, Object value) 复制属性
static <K,V> Map<K,V> createCache() 创建缓存
static Map<String,String> describe(Object bean) 描述
static String[] getArrayProperty(Object bean, String name) 返回指定属性的值,作为字符串数组返回
static String getIndexedProperty(Object bean, String name) 获取指定索引位置对象作为字符串返回
static String getIndexedProperty(Object bean, String name, int index) 获取指定索引位置对象作为字符串返回
static String getMappedProperty(Object bean, String name) 获得Map属性值作为字符串返回
static String getMappedProperty(Object bean, String name, String key) 获得Map属性中指定键的值作为字符串返回
static String getNestedProperty(Object bean, String name) 获得嵌套属性作为字符串返回
static String getProperty(Object bean, String name) 获得属性值作为字符串返回
static String getSimpleProperty(Object bean, String name) 获得属性值作为字符串返回
static void populate(Object bean, Map<String,? extends Object> properties) 将Map中的数据注入到Bean对象中
static void setProperty(Object bean, String name, Object value) 设置属性值

使用示例:

package com.gujin.beanutils;

import java.util.HashMap;

import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;

import com.gujin.entity.UserInfo;

public class BeanUtilsTest
{
   @Test
   public void test() throws Exception
   {
      UserInfo userInfo = new UserInfo();
      HashMap<String, String> properties = new HashMap<String, String>();
      properties.put("userId", "jianggujin");
      properties.put("userName", "蒋固金");
      BeanUtils.populate(userInfo, properties);
      System.out.println(userInfo);
   }
}

运行结果:

{userId:jianggujin,userName:蒋固金}

ConvertUtils

ConvertUtils提供了数据类型相互转换的方法。

方法摘要: 
方法摘要:

返回值 方法名 说明
static String convert(Object value) 将对象转换为字符串
static Object convert(Object value, Class<?> targetType) 将对象转换为指定数据类型对象
static Object convert(String[] values, Class<?> clazz) 将数组转换为指定数据类型对象
static Object convert(String value, Class<?> clazz) 将字符串转换为指定数据类型对象
static void deregister() 移除所有已经注册的转换器
static void deregister(Class<?> clazz) 移除指定类型的转换器
static Converter lookup(Class<?> clazz) 查找指定类型的转换器
static Converter lookup(Class<?> sourceType, Class<?> targetType) 查找将指定类型转换为另一种类型的转换器
static void register(Converter converter, Class<?> clazz) 注册转换器

使用示例:

package com.gujin.beanutils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.junit.Test;

public class ConvertUtilsTest
{
   @Test
   public void test() throws Exception
   {
      ConvertUtils.register(new Converter()
      {

         @Override
         public <T> T convert(Class<T> arg0, Object arg1)
         {
            try
            {
               return (T) new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                     .parse((String) arg1);
            }
            catch (ParseException e)
            {
               return null;
            }
         }
      }, Date.class);

      System.out.println(ConvertUtils
            .convert("2016-04-09 12:41:00", Date.class));
   }
}

运行结果:

Sat Apr 09 12:41:00 CST 2016

猜你喜欢

转载自blog.csdn.net/durenniu/article/details/81606031