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

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

之前一直在接触动态代理,但是对于一些概念还是不能很好得理解,知道模板怎么用,但是换一种方式,我就懵逼了。

为什么会有动态代理呢,先看下面得例子:

由来

1.首先定义一个接口Subject

package com.wx.proxy.jdkproxy;public interface Subject {    void hello(String param);    void say();}

2. 定义接口得实现类SubjectImpl

package com.wx.proxy.jdkproxy;public class SubjectImpl implements Subject {    public void hello(String param) {        System.out.println("hello "+param);    }    public void say() {        System.out.println("增加一个方法");    }}

3. 创建主类,调用say方法

package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Main {    public static void main(String[] args) {        Subject subject = new SubjectImpl();        subject.say();    }}

运行结果:

                                   

如果我想在这个方法前后打印日志,那么在不改动源码得基础上,创建一个代理类SubjectImplProxy,代码如下:

静态代理:

1.在原有基础上,创建SubjectImplProxy

package jdkproxy;public class SubjectImplProxy implements Subject {    private Subject subject= null;    public SubjectImplProxy(Subject subject){        this.subject = subject;    }    @Override    public int hello(String param) {        System.out.println("开始执行hello方法");        subject.hello("world");        System.out.println("结束执行hello方法");        return 0;    }    @Override    public void say() {        System.out.println("开始执行say方法");        subject.say();        System.out.println("结束执行say方法");    }}

2. 测试Main类修改为:

package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Main {    public static void main(String[] args) {        Subject subject = new SubjectImpl();        SubjectImplProxy subjectProxy = new SubjectImplProxy(subject);        subjectProxy.say();    }}

测试结果

                                                                   

这里功能虽然实现,但是有一个问题就是,如果出现SubjectImpl2,或者其他类型得类需要代理,都需要创建一个新的代理类,这样就会很麻烦,为了解决这个问题,就出现了动态代理

JDK动态代理

1. 创建代理实现类SubjectProxy

在此类中。当代理对象执行方法时,会执行invoke方法。通过反射得到method对象,然后执行方法,返回执行方法后的返回值

package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class SubjectProxy implements InvocationHandler{    private Subject subject;    public SubjectProxy(Subject subject){        this.subject = subject;    }    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("-----------------begin--------------------");        Object invoke = method.invoke(subject,args);        System.out.println("-----------------end----------------------");        return invoke;    }}

2. 创建测试类

package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Main {    public static void main(String[] args) {        Subject subject = new SubjectImpl();        SubjectProxy subjectProxy = new SubjectProxy(subject);        Subject proxy = (Subject)Proxy.newProxyInstance(subjectProxy.getClass().getClassLoader(), subject.getClass().getInterfaces(), subjectProxy);        proxy.say();    }}

测试结果:

                                                    

无需创建代理对象类,通过匿名内部类创建

修改后的Main类:

    在此类中,通过匿名内部类创建代理对象,然后判断不同得执行方法,执行不同代码

package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Main {    public static void main(String[] args) {        Subject subject = new SubjectImpl();        SubjectProxy subjectProxy = new SubjectProxy(subject);        Subject proxy = (Subject)Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                if("say".equals(method.getName())){                    System.out.println("=======开始=========");                    Object object = method.invoke(subject,args);                    System.out.println("=======结束=========");                    return object;                }                if("hello".equals(method.getName())){                    System.out.println("=============begin===============");                    Object object = method.invoke(subject,args);                    System.out.println("=============end=================");                    return  object;                }               return null;            }        });        proxy.hello("world");        proxy.say();    }}

CGLIB动态代理

              在jdk代理中,因为需要写实现类。为了直接对基本类进行代理,不要有实现接口,使用CGLIB动态代理。

1. 创建被代理类

     

package cglibProxy;public class CGLIB {    public void sayHello(){        System.out.println("hello world");    }    public void say(){        System.out.println("ceshi");    }}

2. 创建代理类

    创建代理类,实现MethodInterceptor接口

package cglibProxy;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class HelloInterceptor implements MethodInterceptor {    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        System.out.println("begin time -----> "+ System.currentTimeMillis());        Object o1 = methodProxy.invokeSuper(o, objects);        System.out.println("end time -----> "+ System.currentTimeMillis());        return o1;    }}

3. 创建测试类

package cglibProxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class Main {    public static void main(String[] args) {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(CGLIB.class);        enhancer.setCallback(new HelloInterceptor());        CGLIB cglib = (CGLIB) enhancer.create();        cglib.sayHello();        cglib.say();    }}

4. 测试结果

                                                               

5. 另外一种方式测试

使用不需要实现MethodInterceptor接口得类,来代理普通类。使用method来判断,要对哪些方法进行代理。

package cglibProxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class Main {    public static void main(String[] args) {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(CGLIB.class);        //enhancer.setCallback(new HelloInterceptor());        enhancer.setCallback(new MethodInterceptor() {            @Override            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {                if("sayHello".equals(method.getName())){                    System.out.println("begin time -----> "+ System.currentTimeMillis());                    Object o1 = methodProxy.invokeSuper(o, objects);                    System.out.println("end time -----> "+ System.currentTimeMillis());                    return o1;                }else{                    Object o2 = methodProxy.invokeSuper(o, objects);                    return  o2;                }            }        });        CGLIB cglib = (CGLIB) enhancer.create();        cglib.sayHello();        cglib.say();    }}

6. 代理结果

                                                               

转载地址:http://eirdb.baihongyu.com/

你可能感兴趣的文章
专科学院工科毕业,我是如何成为BAT 安卓开发工程师?
查看>>
三分钟让你搞懂Android架构模式
查看>>
重磅来袭:2020 Android开发热门前沿知识
查看>>
干货分享:Android沉浸式状态栏 + scrollView顶部伸缩 + actionBar渐变
查看>>
分享7年Android经验:真的有弄懂过性能优化吗?
查看>>
Android 开源 | 新一代Android 性能监控框架Rabbit
查看>>
Android性能优化:微信自用高性能持久化框架——MMKV组件原理
查看>>
Android开发者相比2019减少28%,Andriod要凉?
查看>>
Android开发者,2020,你还敢再忽视LeakCanary?
查看>>
干货分享:Android RecyclerView(进阶篇)
查看>>
Android设计模式七大原则,原来还可以这么玩?
查看>>
入门:给Android开发者 UI 自动化测试上手指南
查看>>
干货分享:Android图片资源导入之Vector Asset
查看>>
赶紧试试,Android 中心区域选中图表 WheelChart!!!
查看>>
Flutter常用组件-ListView 列表组件
查看>>
从源码的角度去解析Android Fragment (一)
查看>>
从源码的角度去解析Android Fragment(二)
查看>>
入门的Android架构师需要掌握哪些技能?
查看>>
玩GitHub?你必须知道的十个开源项目!!!
查看>>
三分钟带你了解AndroidAutoLayout
查看>>