动态生成类(由Proxy.newProxyInstance想到的)

两种方法:
  1 运行时动态生成文本的.java文件,调用java编译工具类编译成.class二进制文件,就像web服务器将jsp编译成servlet一样
  2 使用asm等bytecode框架动态生成二进制java类,比较麻烦。

 

说穿了就是拼字节码,读懂JAVA的CLASS文件的字节码规范,然后自己按规范拼一个一模一样的字节码,然后用ClassLoader的defineClass读入并生成就好了。 

由于自己拼字节码这个事情非常繁琐非常2,就有很多框架来完成这个事情,比如著名的CGLIB

想完全搞清楚,就只能啃CLASS字节码规范,没别的捷径。
书籍的话推荐看周志明大神的JVM方面的书。

cglib是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。许多开源项目都用到了它,如Hibernate,Spring之类用它来实现动态代理。

cglib 一般在 Spring、Hibernate 的 lib 目录中会找到。如果不是 nodep 版的 jar 还需要 ASM 的支持。

Cglib 中有个 BeanGenerator 就是专门用于做这个的,可以动态生成 JavaBean,
BeanGenerator 利用了非常底层的 ASM 字节码框架来实现的。

 简单样例—动态生成bean

  样例说明:建立一个动态实体bean,使用cglib动态加入属性,和相应的get,set方法。

需要导入cglib-nodep-2.2.jar

been类

Java代码  
  1. public class CglibBean {   
  2. /**  
  3.   * 实体Object  
  4.   */  
  5. public Object object = null;   
  6.   
  7. /**  
  8.   * 属性map  
  9.   */  
  10. public BeanMap beanMap = null;   
  11.   
  12. public CglibBean() {   
  13.   super();   
  14. }   
  15.   
  16. @SuppressWarnings("unchecked")   
  17. public CglibBean(Map propertyMap) {   
  18.   this.object = generateBean(propertyMap);   
  19.   this.beanMap = BeanMap.create(this.object);   
  20. }   
  21.   
  22. /**  
  23.   * 给bean属性赋值  
  24.   * @param property 属性名  
  25.   * @param value 值  
  26.   */  
  27. public void setValue(String property, Object value) {   
  28.   beanMap.put(property, value);   
  29. }   
  30.   
  31. /**  
  32.   * 通过属性名得到属性值  
  33.   * @param property 属性名  
  34.   * @return 值  
  35.   */  
  36. public Object getValue(String property) {   
  37.   return beanMap.get(property);   
  38. }   
  39.   
  40. /**  
  41.   * 得到该实体bean对象  
  42.   * @return  
  43.   */  
  44. public Object getObject() {   
  45.   return this.object;   
  46. }   
  47.   
  48. @SuppressWarnings("unchecked")   
  49. private Object generateBean(Map propertyMap) {   
  50.   BeanGenerator generator = new BeanGenerator();   
  51.   Set keySet = propertyMap.keySet();   
  52.   for (Iterator i = keySet.iterator(); i.hasNext();) {   
  53.    String key = (String) i.next();   
  54.    generator.addProperty(key, (Class) propertyMap.get(key));   
  55.   }   
  56.   return generator.create();   
  57. }   
  58. }  
public class CglibBean {
/**
  * 实体Object
  */
public Object object = null;

/**
  * 属性map
  */
public BeanMap beanMap = null;

public CglibBean() {
  super();
}

@SuppressWarnings("unchecked")
public CglibBean(Map propertyMap) {
  this.object = generateBean(propertyMap);
  this.beanMap = BeanMap.create(this.object);
}

/**
  * 给bean属性赋值
  * @param property 属性名
  * @param value 值
  */
public void setValue(String property, Object value) {
  beanMap.put(property, value);
}

/**
  * 通过属性名得到属性值
  * @param property 属性名
  * @return 值
  */
public Object getValue(String property) {
  return beanMap.get(property);
}

/**
  * 得到该实体bean对象
  * @return
  */
public Object getObject() {
  return this.object;
}

@SuppressWarnings("unchecked")
private Object generateBean(Map propertyMap) {
  BeanGenerator generator = new BeanGenerator();
  Set keySet = propertyMap.keySet();
  for (Iterator i = keySet.iterator(); i.hasNext();) {
   String key = (String) i.next();
   generator.addProperty(key, (Class) propertyMap.get(key));
  }
  return generator.create();
}
}

 

 

 

 

 

 

再写一个测试类

Java代码  
  1. package com.infotech.cglibTest;   
  2.   
  3. import java.lang.reflect.Method;   
  4. import java.util.HashMap;   
  5.   
  6. /**  
  7.  * Cglib测试类  
  8.  * @author cuiran  
  9.  * @version 1.0  
  10.  */  
  11. public class CglibTest {   
  12.        
  13.        
  14.        
  15.     @SuppressWarnings("unchecked")   
  16.     public static void main(String[] args) throws ClassNotFoundException {   
  17.   
  18.         // 设置类成员属性   
  19.         HashMap propertyMap = new HashMap();   
  20.   
  21.         propertyMap.put("id", Class.forName("java.lang.Integer"));   
  22.   
  23.         propertyMap.put("name", Class.forName("java.lang.String"));   
  24.   
  25.         propertyMap.put("address", Class.forName("java.lang.String"));   
  26.   
  27.         // 生成动态 Bean   
  28.         CglibBean bean = new CglibBean(propertyMap);   
  29.   
  30.         // 给 Bean 设置值   
  31.         bean.setValue("id", new Integer(123));   
  32.   
  33.         bean.setValue("name", "454");   
  34.   
  35.         bean.setValue("address", "789");   
  36.   
  37.         // 从 Bean 中获取值,当然了获得值的类型是 Object   
  38.   
  39.         System.out.println("  >> id      = " + bean.getValue("id"));   
  40.   
  41.         System.out.println("  >> name    = " + bean.getValue("name"));   
  42.   
  43.         System.out.println("  >> address = " + bean.getValue("address"));   
  44.   
  45.         // 获得bean的实体   
  46.         Object object = bean.getObject();   
  47.   
  48.         // 通过反射查看所有方法名   
  49.         Class clazz = object.getClass();   
  50.         Method[] methods = clazz.getDeclaredMethods();   
  51.         for (int i = 0; i < methods.length; i++) {   
  52.             System.out.println(methods[i].getName());   
  53.         }   
  54.     }  
package com.infotech.cglibTest;

import java.lang.reflect.Method;
import java.util.HashMap;

/**
 * Cglib测试类
 * @author cuiran
 * @version 1.0
 */
public class CglibTest {
	
	
	
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws ClassNotFoundException {

		// 设置类成员属性
		HashMap propertyMap = new HashMap();

		propertyMap.put("id", Class.forName("java.lang.Integer"));

		propertyMap.put("name", Class.forName("java.lang.String"));

		propertyMap.put("address", Class.forName("java.lang.String"));

		// 生成动态 Bean
		CglibBean bean = new CglibBean(propertyMap);

		// 给 Bean 设置值
		bean.setValue("id", new Integer(123));

		bean.setValue("name", "454");

		bean.setValue("address", "789");

		// 从 Bean 中获取值,当然了获得值的类型是 Object

		System.out.println("  >> id      = " + bean.getValue("id"));

		System.out.println("  >> name    = " + bean.getValue("name"));

		System.out.println("  >> address = " + bean.getValue("address"));

		// 获得bean的实体
		Object object = bean.getObject();

		// 通过反射查看所有方法名
		Class clazz = object.getClass();
		Method[] methods = clazz.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			System.out.println(methods[i].getName());
		}
	}

  

posted @ 2014-03-20 14:41  ftefno  阅读(199)  评论(0)    收藏  举报