java jdk动态代理模式举例浅析

柔情痞子 提交于 2020-02-27 10:30:37

代理模式概述

代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色。

java中常用的动态代理模式为jdk动态代理和cglib动态代理。

 

反射技术

了解动态代理之前,需要先了解一下java中的反射,反射在框架中的应用非常广泛,它能够配置:类的全限定名,方法和参数。在运行时,动态的完成类的初始化,或者反射调用某些方法。

我们可以通过Class.forName()方法加载类,并用getConstructor方法配置参数。例:

object = (goodsServiceImpl)=Class.forName("com.xjx.test.goodsServiceImpl").getConstructor(String.class).newInstance("计算机");

 

1. jdk动态代理举例

jdk动态代理由java.lang.reflect.*包提供,它必须借助一个接口才能实现代理。

我们举个例子来实现jdk动态代理并简要分析:

首先我们定义一个接口:

public interface jdkProxy {
    public void test(String tString);
}

以及它的实现类:

public class jdkProxyImpl implements jdkProxy{
    @Override
    public void test(String tString) {
        // TODO Auto-generated method stub
        System.out.println("代理内方法"+tString);
    }  
}

接下来我们要进行代理。代理过程分2步:

1.建立起代理对象和真实服务对象之间的关系,生产代理对象;

2.实现逻辑的代理;

在jdk动态代理中,要实现代理逻辑就必须实现InvocationHandler接口。它里面定义了一个invoke方法,每当我们通过代理对象调用方法时,它都会被转发到这个invoke方法,我们来

定义一个实现代理逻辑的类:

public class jdkProxyExample implements InvocationHandler{ 
    //真实对象
    private Object target = null; 
    /**
     * 建立真实对象和代理对象的代理关系
     * @param target真实对象
     * @return 代理对象
     */
    public Object setTargetAndBind(Object target) {
        this.target = target;
        /**
         * 参数1:getClassLoader()提供类加载器;        参数2:getInterfaces()要挂载动态代理对象的接口,就是target的接口;
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);  
    }
    /**
     * 代理方法逻辑
     * @param:代理对象
     * method:当前调度方法
     * args:当前方法参数
     * return 代理结果返回
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("进入代理对象方法,在此执行代理对象之前的一些操作");
        //执行目标对象中的某个方法
        Object object = method.invoke(target, args);
        System.out.println("调用代理对象方法之后的操作");
        return object;
    }
}
1.1 生成一个代理对象

setTargetAndBind()这个方法内的newProxyInstance()方法通过传入被代理内,再通过反射,生成一个代理类。

1.2 实现代理类的逻辑方法

object obj = method.invoke(target,args),这个方法相当于调度真实对象的方法,只不过是通过反射区实现。它返回方法的执行结果。

并且在invoke方法里,可以在调用真实对象方法之前和之后做一些其他的操作,这也是AOP的实现原理

 

这样,一个jdk动态代理就完成了,接下来可以写个测试类测试一下:

 

public class jdkProxyExampleTest {

    @Test
    public void testProxy() {
        jdkProxyExample jdkProxyExample = new jdkProxyExample();
        //绑定关系,此时jdkProxy已经是一个代理对象
        jdkProxy jdkProxy = (jdkProxy)jdkProxyExample.setTargetAndBind(new jdkProxyImpl());
        //执行代理对象方法
        jdkProxy.test("动态代理jdk");
    }
}

 

打印结果如下:

 

2. 为什么jdk动态代理一定需要目标对象实现接口?(可能有误

1.我们可以看到,在绑定关系的方法中,实现被代理类的反射,需要我们提供接口,然后它通过接口实现代理类。没有它就找不到反射的方法。

2.由于java的单继承机制:首先jdk动态代理是通过newInstance动态的生成代理对象的,newInstance通过ProxyGenerator生成的字节码代表的类继承了Proxy类:

public final class $Proxy0 extends Proxy
  implements jdkProxy{
    ...
}
$Proxy0这个类通过反编译获得,它就是jdkProxy的实现类的动态的代理类。
由于java的单继承机制,被代理对象不能再被其他的类继承,那么我们如果想建立代理类和被代理类之间的关系,只能通过实现同一个接口了。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!