JAVA的动态代理入门

Java动态代理采用反射的机制,在程序运行时动态生成代理类。我们可以采用Java动态代理机制来对被代理类的一些方法实现增强的行为。Spring的APO也是基于动态代理来实现的。
实现动态代理有两种方法,第一种是基于JDK的Proxy类,一种是基于CGLIB。JDK的动态代理只能是针对于接口代理,如果需要对类进行动态代理只能使用CGLIB了。本篇博客之讨论基于JDK的动态代理。
首先,我们需要一个接口,代理类和真实类都要实现这个接口(或者真实类和代理类同时实现多个相同的接口)。比如,我们可以定义如下的接口:

public interface ISubject {

    public String sayHello();

    public String waterFlower();

}

接着,定义一个类,实现这个接口

public class RealSubject implements ISubject {

    @Override
    public String sayHello() {
        PrintUtils.printlnString("打招呼。");
        return "做一个有礼貌的好学生";
    }

    @Override
    public String waterFlower() {
        PrintUtils.printlnString("我在浇花。");
        return "做一个喜欢花花草草的有情趣的人";
    }
}

现在,我们定义一个代理类,需要实现InvocationHandler接口。
bind方法生成一个代理对象,因为Proxy.newProxyInstance的第二个参数使用的是真实类的接口realObject.getClass().getInterfaces(),所以代理对象可以调用真实类的接口方法。当代理对象调用真实类接口方法的时候就会调用invoke方法。

public class DynamicProxy implements InvocationHandler {

    //需要代理的真实对象
    private Object realObject;


    public Object bind(Object realObject) {
        //给代理的真实对象赋值
        this.realObject = realObject;
        /**
         * 通过Proxy.newProxyInstance创建代理对象,需要三个参数
         *    1 realObject.getClass().getClassLoader() 类加载路径
         *    2 realObject.getClass().getInterfaces()  真实类的接口
         *    3 this 将代理对象关联到InvocationHandler
         *
         *    通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,
         *    它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在
         *    运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后
         *    一个数字表示对象的标号。
         */
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                realObject.getClass().getInterfaces(), this);
    }


    /**
     * 在代理对象上处理一个方法调用,返回处理结果
     *
     * @param proxy  动态代理类的对象
     * @param method 被拦截的方法
     * @param args   被拦截的方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        PrintUtils.printlnString("=========我是JDK动态代理===========");
        PrintUtils.printlnString("method的名字是:" + method.getName());
        Object obj = method.invoke(realObject, args);
        PrintUtils.printlnString(obj.toString());
        PrintUtils.printlnString("完成方法的调用");
        return obj;
    }
}
public class TestProxy {

    @Test
    public void testJDKProxy() {
        DynamicProxy proxyHandler = new DynamicProxy();
        //创建代理对象
        ISubject proxy = (ISubject) proxyHandler.bind(new RealSubject());
        proxy.sayHello();
        proxy.waterFlower();
    }
}

执行打印的日志:
=========我是JDK动态代理===========
method的名字是:sayHello
打招呼。
做一个有礼貌的好学生
完成方法的调用
=========我是JDK动态代理===========
method的名字是:waterFlower
我在浇花。
做一个喜欢花花草草的有情趣的人
完成方法的调用

到这里,我们用一个例子完成了基于JDK的动态代理的入门学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值