博客
关于我
强烈建议你试试无所不能的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/

你可能感兴趣的文章
PAT刷题笔记
查看>>
Keeping on the ground , looking at the sky.
查看>>
提高深度神经网络性能的一些技巧
查看>>
ICT_TASK_1
查看>>
Ubuntu多用户Anaconda环境配置
查看>>
金字塔问题(动态规划)
查看>>
安装Fedora系统和一些系统配置
查看>>
安装docker
查看>>
怎样解决在单例对象中注入原生对象失效
查看>>
搭建spring cloud项目的依赖管理
查看>>
docker运行eureka服务注册中心
查看>>
内部类小结
查看>>
反射小结
查看>>
java中的类锁和对象锁对比分析
查看>>
使用maven搭建一个简单的SSM框架
查看>>
高性能MySQL笔记:第一章
查看>>
MySQL-8.0.12数据库的卸载,安装和海量sql数据导入
查看>>
后台权限管理项目总结
查看>>
JavaSE基础之IO流
查看>>
JavaSE基础之线程
查看>>