博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java动态代理
阅读量:5111 次
发布时间:2019-06-13

本文共 3046 字,大约阅读时间需要 10 分钟。

所谓代理,又分为静态代理和动态代理两种。在介绍动态代理之前,我们先了解下在Java中静态代理的使用方式和局限性。

假设当前我们有一个功能接口,需要通过代理类来调用该功能接口的实现类。我们可以使用静态代理调用的方式进行处理,在代理中可以执行额外的处理代码(如日志打印、执行时间的统计等等),代码如下:

/** * 功能接口 */interface Duck {    void info();    void say();}/** * 功能接口实现类 */class RealDuck implements Duck {    @Override    public void info() {        System.out.println("鸭子");    }    @Override    public void say() {        System.out.println("我是一只鸭子");    }}/** * 代理类 */class DuckProxy implements Duck {    private Duck duck;    public DuckProxy(Duck duck) {        this.duck = duck;    }    @Override    public void info() {        System.out.println("调用前--->");        duck.info();        System.out.println("调用后--->");    }    @Override    public void say() {        System.out.println("调用前--->");        duck.say();        System.out.println("调用后--->");    }}public class TestStaticProxy {    public static void main(String[] args) {        // 创建被代理类对象        Duck realDuck = new RealDuck();                // 创建代理类对象,将通过该对象进行被代理类的调用        Duck duckProxy = new DuckProxy(realDuck);        // 调用代理类对象的方法,转而调用被代理类的方法        duckProxy.info();        // 同上        duckProxy.say();    }}

 以上,我们实现了一个静态代理。其存在一个弊端:假设要增加另外的一个接口则需要一个与之配对的另一个代理,这样会导致类的爆炸。。。此时我们可以引入动态代理来规避此类问题,减少代码的冗余

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * @author luhuancheng * @since 2018/2/8 23:15 */interface Human {    void info();    void say();}/** * 被代理类 */class SuperMan implements Human {    @Override    public void info() {        System.out.println("超人来了......");    }    @Override    public void say() {        System.out.println("我是超人......");    }}/** * 日志工具 */class LogUtils {    public static void before() {        System.out.println("调用前时间" + System.currentTimeMillis());    }    public static void after() {        System.out.println("调用后时间" + System.currentTimeMillis());    }}class MyInvocationHandler implements InvocationHandler {    private Object object;    public void setObject(Object object) {        this.object = object;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        LogUtils.before();        Object result = method.invoke(object, args);        LogUtils.after();        return result;    }}class MyProxy {    public static Object getProxy(Object object) {        MyInvocationHandler handler = new MyInvocationHandler();        handler.setObject(object);        // 返回一个代理类对象。该代理类实现了与对象object一致的接口。        // 并且在调用该代理类对象的相关方法时,转而调用其 invoke(Object proxy, Method method, Object[] args)方法;        // 实现了对模版代码的重用,并且避免了代理类与被代理类必须成对存在的弊端        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), handler);    }}public class TestDynamicProxy {    public static void main(String[] args) {        SuperMan superMan = new SuperMan();        Object object = MyProxy.getProxy(superMan);        Human man = (Human) object;        man.info();        man.say();    }}

 

转载于:https://www.cnblogs.com/luhuancheng1992/p/8433859.html

你可能感兴趣的文章
伪类与超链接
查看>>
centos 7 redis-4.0.11 主从
查看>>
博弈论 从懵逼到入门 详解
查看>>
永远的动漫,梦想在,就有远方
查看>>
springboot No Identifier specified for entity的解决办法
查看>>
慵懒中长大的人,只会挨生活留下的耳光
查看>>
"远程桌面连接--“发生身份验证错误。要求的函数不受支持
查看>>
【BZOJ1565】 植物大战僵尸
查看>>
视频:"我是设计师"高清完整版Plus拍摄花絮
查看>>
VALSE2019总结(4)-主题报告
查看>>
浅谈 unix, linux, ios, android 区别和联系
查看>>
51nod 1428 活动安排问题 (贪心+优先队列)
查看>>
中国烧鹅系列:利用烧鹅自动执行SD卡上的自定义程序(含视频)
查看>>
Solaris11修改主机名
查看>>
latex for wordpress(一)
查看>>
如何在maven工程中加载oracle驱动
查看>>
Flask 系列之 SQLAlchemy
查看>>
aboutMe
查看>>
【Debug】IAR在线调试时报错,Warning: Stack pointer is setup to incorrect alignmentStack,芯片使用STM32F103ZET6...
查看>>
一句话说清分布式锁,进程锁,线程锁
查看>>