动态编译

javassist

<!-- https://mvnrepository.com/artifact/javassist/javassist -->
<dependency>
    <groupId>javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.12.1.GA</version>
</dependency>
package com.noob;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.NotFoundException;
import lombok.Data;

import com.zhongan.fcp.pre.allin.common.utils.JSONUtils;

public class TestJavassist {

	public static void main(String[] args) {
		try {

			ByteArrayOutputStream bo = new ByteArrayOutputStream();
			ObjectOutputStream readIn = new ObjectOutputStream(bo);
			readIn.writeObject(modifyClass());
			ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
			ObjectInputStream writeOut = new ObjectInputStream(bi);
			A b = A.class.cast(writeOut.readObject()); // 反序列化对象类型是序列化对象的父类或本身
			System.out.println(JSONUtils.toFormatJsonString(b));
			System.out.println(b.getA());

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static Object modifyClass() throws NotFoundException,
			CannotCompileException, IntrospectionException,
			InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		ClassPool pool = ClassPool.getDefault();
		// 获取一个A类的CtClass对象
		CtClass ctClass = pool.get("com.noob.A");
		// 为ctClass设置一个父类
		ctClass.setSuperclass(pool.get("com.noob.B"));
		// 为cTclass对象添加一个属性name
		ctClass.addField(CtField.make("private String addField;", ctClass));
		ctClass.addMethod(CtMethod
				.make("public void setAddField(String addField){this.addField = addField;}",
						ctClass));
		ctClass.addMethod(CtMethod.make(
				"public String getAddField(){return this.addField;}", ctClass));

		ctClass.removeField(ctClass.getDeclaredField("a"));
		ctClass.removeMethod(ctClass.getDeclaredMethod("getA"));
		ctClass.removeMethod(ctClass.getDeclaredMethod("setA"));

		// 获取ctClass对象对应的Class对象cls
		Class cls = ctClass.toClass();
		// 对cls类进行内省,得到对象BeanInfo
		BeanInfo beanInfo = Introspector.getBeanInfo(cls, Object.class);
		// 获取beanInfo的方法描述对象
		MethodDescriptor[] descriptors = beanInfo.getMethodDescriptors();

		for (int i = 0; i < descriptors.length; i++) {
			System.out.println("--- modify class method:----"
					+ descriptors[i].getName());
		}

		PropertyDescriptor[] propertyDescriptors = beanInfo
				.getPropertyDescriptors();
		for (int i = 0; i < propertyDescriptors.length; i++) {
			System.out.println("--- modify class field:----"
					+ propertyDescriptors[i].getDisplayName());
		}
		System.out.println("-------------------------------");
		for (Method method : A.class.getDeclaredMethods()) {
			System.out.println("---after modify A.class method----"
					+ method.getName());
		}
		for (Field field : A.class.getDeclaredFields()) {
			System.out.println("---after modify A.class field----"
					+ field.getName());
		}
		Object obj = cls.newInstance();
		for (Method method : cls.getDeclaredMethods()) {
			if (method.getName().startsWith("set")) {
				method.invoke(obj, "test" + method.getName());
			}
		}
		return obj;
	}
}

@Data
class A implements Serializable {

	private static final long serialVersionUID = 1L;
	private String a, b, c;

}

@Data
class B implements Serializable {

	private static final long serialVersionUID = 1L;
	private String d, e, f;

}

【新增 字段、方法】

【删除 字段、方法】

猜你喜欢

转载自my.oschina.net/u/3434392/blog/1604745