JDK-Proxy示例

JDK 从1.3开始提供的 Proxy 工具类, 以提供用代理的方式去执行某个接口的某些方法, 在Spring AOP的实现中就有应用;

JDK: 1.8


代码示例

1 . 需要被代理的接口

package com.test.reflect;

/**
 * @author Hinsteny
 * @Describtion
 * @date 2016/12/2
 * @copyright: 2016 All rights reserved.
 */
public interface Scholar {

    String LOCAL = "CHIBA";

    String  searching(String theme);

    default String infoLocal(){
        return this.LOCAL;
    }
}

2 . 需要被代理的实现类

package com.test.reflect;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;

/**
 * @author Hinsteny
 * @Describtion
 * @date 2016/12/2
 * @copyright: 2016 All rights reserved.
 */
public class ScholarImpl implements Scholar {

    static final private Logger logger = LoggerFactory.getLogger(ScholarImpl.class);

    public static String printTime(){
        logger.info("Now time is {}", LocalDateTime.now().toString());
        return "Time";
    }

    @Override
    public String searching(String theme) {
        logger.info("Scholar do search {}", theme);
        return "success";
    }
}

3 . 实现InvocationHandler接口, 这里是代理执行的地方, 可以加入自定义业务逻辑(比如日志记录, 权限拦截, 统计等)

package com.test.reflect.jdk;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @author Hinsteny
 * @Describtion
 * @date 2016/12/2
 * @copyright: 2016 All rights reserved.
 */
public class MyHandler implements InvocationHandler {

    static final private Logger logger = LoggerFactory.getLogger(MyHandler.class);

    private Object object = null;

    public MyHandler(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        logger.info("do something before method {}", method.getName());
        Object ret = method.invoke(this.object, args);
        logger.info("do something after method {}", method.getName());

        return ret;
    }
}

4 . 查看代理效果的测试用例, 及生成代理类的class文件

package com.test.reflect.jdk;

import com.test.reflect.Scholar;
import com.test.reflect.ScholarImpl;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;

/**
 * @author Hinsteny
 * @Describtion
 * @date 2016/12/2
 * @copyright: 2016 All rights reserved.
 */
public class JDKProxyTest {

    static final private Logger logger = LoggerFactory.getLogger(JDKProxyTest.class);

    @Test
    public void testProxy(){
        // 元对象(被代理对象)
        ScholarImpl managerImpl = new ScholarImpl();

        // 业务代理类
        MyHandler securityHandler = new MyHandler(managerImpl);

        // 获得代理类($Proxy0 extends Proxy implements Manager)的实例.
        Scholar managerProxy = (Scholar) Proxy.newProxyInstance(JDKProxyTest.class.getClassLoader(), managerImpl.getClass().getInterfaces(), securityHandler);

        logger.info("Scholar local is {}", managerProxy.LOCAL);
        logger.info("Scholar default method do and result is {}", managerProxy.infoLocal());
        String theme = "knowledge";
        String result = managerProxy.searching(theme);
        logger.info("result is {}", result);
    }

    @Test
    public void testGetProxyClass_1(){
        // 需要添加java命令执行时参数 [-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true]
        // 然后生成的动态代理对象会在下面目录的子目录 [com\sun\proxy] 中, 命名是从 [$Proxy#.class](#从0开始依次加1递增)
        System.out.println(System.getProperty("user.dir"));
        testProxy();
        // 可以去对应目录去查看生成的动态class类文件, 反编译出动态类的java代码
        logger.info("Finish at here {}");
    }

    @Test
    public void testGetProxyClass_2(){
        // 获取代理类的字节码
        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", ScholarImpl.class.getInterfaces());
        // 写入文件
        String path = "D://data/$Proxy1.class";
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(path);
            out.write(classFile);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null)
                    out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

5 . 反编译查看生成动态类源代码


package com.sun.proxy;

import com.test.reflect.*;
import java.lang.reflect.*;

public final class $Proxy20 extends Proxy implements Scholar
{
    private static Method m1;
    private static Method m2;
    private static Method m4;
    private static Method m3;
    private static Method m0;

    public $Proxy20(final InvocationHandler invocationHandler) {
        super(invocationHandler);
    }

    public final boolean equals(final Object o) {
        try {
            return (boolean)super.h.invoke(this, $Proxy20.m1, new Object[] { o });
        }
        catch (Error | RuntimeException error) {
            throw;
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final String toString() {
        try {
            return (String)super.h.invoke(this, $Proxy20.m2, null);
        }
        catch (Error | RuntimeException error) {
            throw;
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final String infoLocal() {
        try {
            return (String)super.h.invoke(this, $Proxy20.m4, null);
        }
        catch (Error | RuntimeException error) {
            throw;
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final String searching(final String s) {
        try {
            return (String)super.h.invoke(this, $Proxy20.m3, new Object[] { s });
        }
        catch (Error | RuntimeException error) {
            throw;
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final int hashCode() {
        try {
            return (int)super.h.invoke(this, $Proxy20.m0, null);
        }
        catch (Error | RuntimeException error) {
            throw;
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    static {
        try {
            $Proxy20.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            $Proxy20.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
            $Proxy20.m4 = Class.forName("com.test.reflect.Scholar").getMethod("infoLocal", (Class<?>[])new Class[0]);
            $Proxy20.m3 = Class.forName("com.test.reflect.Scholar").getMethod("searching", Class.forName("java.lang.String"));
            $Proxy20.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
        }
        catch (NoSuchMethodException ex) {
            throw new NoSuchMethodError(ex.getMessage());
        }
        catch (ClassNotFoundException ex2) {
            throw new NoClassDefFoundError(ex2.getMessage());
        }
    }
}

注:

猜你喜欢

转载自blog.csdn.net/hinstenyhisoka/article/details/53470364
今日推荐