简单使用JDK的Proxy.newProxyInstance()方法

JDK的动态代理实现的原理其实是动态生成Proxy的.java文件,再动态编译.java文件成为对应的.class文件,再通过ClassLoader将字节码对象加载到内存中从而实现动态的效果。现在主要是测试一下如何使用JDK的动态代理,不做原理的分析。如果想了解原理可以观看马士兵的设计模式之动态代理深入剖析。

package cn.shaines.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.List;

/**
 * 定义一个接口
 */
interface MyInterface {
    int getInt(int i);
    void close();
}

/**
 * 接口实现类
 */
class MyInterfaceImpl implements MyInterface {
    @Override
    public int getInt(int i) {
        return i;
    }
    @Override
    public void close() {
        System.out.println("==>>close()");
    }

    public void otherMethod(){
        System.out.println("==>>otherMethod()");
    }
}

/**
 * 测试类JDK代理
 */
public class Test {

    /**
     * 反射执行方法
     * @param o 调用对象
     * @param methodName 方法名称
     * @param parameterTypes 参数类型.class
     * @param parameters 参数实体
     */
    public static <R> R methodInvoke(Object o, String methodName, Class<?>[] parameterTypes, Object[] parameters) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        return (R) ((parameterTypes == null) ? o.getClass().getMethod(methodName).invoke(o) : o.getClass().getMethod(methodName, parameterTypes).invoke(o, parameters));
    }

    // 入口main
    public static void main(String[] args) {

        // 使用JDK提供的动态代理方法步骤如下:
        // 步骤01: 创建需要代理的实体类对象
        MyInterfaceImpl myInterfaceImpl = new MyInterfaceImpl();
        // 步骤02: 获取实体类对象的Class对象
        Class<? extends MyInterfaceImpl> clazz = myInterfaceImpl.getClass();
        // 步骤03: 调用JDK提供的Proxy.newProxyInstance()方法
        Object proxyInstance = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 步骤04: 动态修改getInt()方法
                if (method.getName().equals("getInt")){
                    System.out.println("代理类收到的参数是:" + args[0]);
                    return 100;
                }
                // 步骤05: 注意这里的实际调用必须是实现类对象
                return method.invoke(myInterfaceImpl);
            }
        });

        // cn.shaines.test.MyInterfaceImpl
        System.out.println(clazz.getClass().getName());
        // java.lang.Class
        System.out.println(clazz.getName());

        // 步骤06: 使用代理对象(强制转换为接口对象MyInterface,不可以强制转换为MyInterfaceImpl,
        //         通过上面的打印可以知道proxyInstance的class和MyInterfaceImpl的class是不同的,强制转换会报错)
        // MyInterfaceImpl myInterfaceImpl2 = ((MyInterfaceImpl) proxyInstance);// 报错
        MyInterface myInterface1 = ((MyInterface) proxyInstance);
        int anInt = myInterface1.getInt(20);
        System.out.println("anInt:" + anInt);// anInt:100     被动态修改值
        myInterface1.close();

        // 放射执行方法,无需强制转为对象都可以使用proxyInstance调用任意方法
        try {
            int i = methodInvoke(proxyInstance, "getInt", new Class[]{int.class}, new Object[]{10});
            methodInvoke(proxyInstance, "close", new Class[]{}, new Object[]{});
            // methodInvoke(proxyInstance, "otherMethod", new Class[]{}, new Object[]{});
            // 这个方法会报错:java.lang.NoSuchMethodException: cn.shaines.test.$Proxy0.otherMethod()
            // 找不到该方法,原因很简单,该动态代理对象是实现接口(MyInterface),不是继承接口实现类(MyInterfaceImpl),所以只有接口的方法,没有具体实现对象(myInterfaceImpl)的方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java动态代理是一种在运行时动态生成代理对象的技术。它可以代理某个接口或者类,使得代理对象可以拦截到对被代理对象的方法调用,并在调用前后进行一些额外的操作,比如记录日志、权限控制等。 Java提供了两种动态代理的实现方式:基于JDK的动态代理和基于CGLIB的动态代理。其中,基于JDK的动态代理只能代理实现了接口的类,而基于CGLIB的动态代理则可以代理任何类,包括没有实现接口的类。 下面是一个基于JDK的动态代理的简单实例: ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface Hello { void sayHello(); } class HelloImpl implements Hello { public void sayHello() { System.out.println("Hello, world!"); } } class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before invoking " + method.getName()); Object result = method.invoke(target, args); System.out.println("After invoking " + method.getName()); return result; } } public class Main { public static void main(String[] args) { Hello hello = new HelloImpl(); InvocationHandler handler = new MyInvocationHandler(hello); Hello proxy = (Hello) Proxy.newProxyInstance( Main.class.getClassLoader(), new Class[] { Hello.class }, handler); proxy.sayHello(); } } ``` 这里定义了一个接口`Hello`和它的实现类`HelloImpl`。`MyInvocationHandler`是一个实现了`InvocationHandler`接口的类,它负责拦截并处理对`Hello`接口方法调用。`Main`类中创建了一个`HelloImpl`对象和一个`MyInvocationHandler`对象,然后调用`Proxy.newProxyInstance`方法构造一个代理对象。通过代理对象调用`sayHello`方法时,`MyInvocationHandler`会先打印一行`Before invoking sayHello`,然后再调用`HelloImpl`对象的`sayHello`方法,最后打印一行`After invoking sayHello`。 下面是一个基于CGLIB的动态代理的简单实例: ```java import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; class Hello { public void sayHello() { System.out.println("Hello, world!"); } } class MyMethodInterceptor implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Before invoking " + method.getName()); Object result = proxy.invokeSuper(obj, args); System.out.println("After invoking " + method.getName()); return result; } } public class Main { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Hello.class); enhancer.setCallback(new MyMethodInterceptor()); Hello hello = (Hello) enhancer.create(); hello.sayHello(); } } ``` 这里定义了一个类`Hello`和它的一个方法`sayHello`。`MyMethodInterceptor`是一个实现了`MethodInterceptor`接口的类,它负责拦截并处理对`Hello`类的方法调用。`Main`类中创建了一个`Enhancer`对象,通过`setSuperclass`方法指定要代理的类,通过`setCallback`方法指定拦截器,然后调用`create`方法构造一个代理对象。通过代理对象调用`sayHello`方法时,`MyMethodInterceptor`会先打印一行`Before invoking sayHello`,然后再调用`Hello`对象的`sayHello`方法,最后打印一行`After invoking sayHello`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值