美文网首页
java动态增加方法

java动态增加方法

作者: 繁星若尘啊 | 来源:发表于2017-10-25 23:02 被阅读1034次

java动态增加方法

package com.lux.study.assist;

import javassist.*;

/**
 * @author: lux
 * @date: 2017/10/25 14:54
 */
public class App {
    public static void main(String[] args) {
        try {
            String className = "com.lux.study.assist.UserInfo";
            UserInfo userInfo = new UserInfo();
            userInfo.setName("test");
            userInfo.setId(1);
            System.out.println("before:" + userInfo);
            ClassPool pool = ClassPool.getDefault();
            CtClass cc = pool.get(className);
            CtMethod mthd = CtNewMethod.make("public String test() { return \"test() is called \"+ toString();  }", cc);
            cc.addMethod(mthd);

            AppClassLoader appClassLoader = AppClassLoader.getInstance();
            Class<?> clazz = appClassLoader.findClassByBytes(className, cc.toBytecode());
//            clazz.getDeclaredConstructor().newInstance();
            Object obj = appClassLoader.getObj(clazz,userInfo);
            System.out.println("after:" + obj);
            //测试反射调用添加的方法
            System.out.println(obj.getClass().getDeclaredMethod("test").invoke(obj));

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

    }

}

package com.lux.study.assist;


import java.lang.reflect.Field;

/**
 * @author: lux
 * @date: 2017/10/24 13:48
 */
public class AppClassLoader extends ClassLoader {

    private static class SingletonHolder {
        public final static AppClassLoader instance = new AppClassLoader();
    }

    public static AppClassLoader getInstance() {
        return SingletonHolder.instance;
    }


    private AppClassLoader() {

    }

    /**
     * 通过classBytes加载类
     *
     * @param className
     * @param classBytes
     * @return
     */
    public Class<?> findClassByBytes(String className, byte[] classBytes) {
        return defineClass(className, classBytes, 0, classBytes.length);
    }

    /**
     * 复制对象所有属性值,并返回一个新对象
     *
     * @param srcObj
     * @return
     */
    public Object getObj(Class<?> clazz, Object srcObj) {
        try {
            Object newInstance = clazz.getDeclaredConstructor().newInstance();
            Field[] fields = srcObj.getClass().getDeclaredFields();
            for (Field oldInstanceField : fields) {
                String fieldName = oldInstanceField.getName();
                oldInstanceField.setAccessible(true);
                Field newInstanceField = newInstance.getClass().getDeclaredField(fieldName);
                newInstanceField.setAccessible(true);
                newInstanceField.set(newInstance, oldInstanceField.get(srcObj));
            }
            return newInstance;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

package com.lux.study.assist;

/**
 * @author: lux
 * @date: 2017/10/24 13:51
 */
public class UserInfo {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

before:UserInfo{id=1, name='test'}
after:UserInfo{id=1, name='test'}
test() is called UserInfo{id=1, name='test'}

借鉴了spring devtool的热部署思想,通过使用javassist或者cglib来实现字节码的生成,然后通过自定义的类加载器加载修改之后的类,最后使用反射实现属性值的拷贝,最后就可以得到一个和之前看起来差不多的类,但是却有我们自定义方法的对象。

相关文章

  • java动态增加方法

    java动态增加方法 借鉴了spring devtool的热部署思想,通过使用javassist或者cglib来实...

  • cocos js在带虚拟按键的手机上的适配

    cocos js在带虚拟按键的手机上的动态调整 在Cocos2dxRenderer.java中增加native方法...

  • 有疑问的地方

    反射和动态代理:java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模...

  • JDK1.7新增的MethodHandle方法与反射调用的例子

    java中通过类调用类的方法之前一直使用反射的机制去做,但是jdk1.7中增加了对动态语言的支持,增加了Metho...

  • Java反射

    一. Class类 二. Java动态加载类 三. Java获取方法信息 四. Java方法反射的基本操作

  • JAVA-Reflect

    一、Class类的使用 二、Java动态加载类 三、Java获取方法信息 四、Java方法的反射

  • Java反射与动态代理

    Java反射 Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制 特点:...

  • JNI基础(3): Java中调用JNI方法

    3.1 Java中加载动态库 java中通过系统提供的如下方法来加载动态库。 ps: java中的static代码...

  • Java动态代理

    java动态代理 先看Method反射,调用getDeclaredMethod查找方法;invoke执行方法,返回...

  • java反射机制

    java反射机制是为了动态获取类的结构,动态地调用对象的方法 java反射机制 获取类Class对象 A.clas...

网友评论

      本文标题: java动态增加方法

      本文链接:https://www.haomeiwen.com/subject/smacpxtx.html