PerKins Zhu

Le vent se lève,il faut tenter de vivre.
随笔 - 87, 文章 - 0, 评论 - 45, 阅读 - 21万

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

动态代理的两种实现方式(JDK/Cglib)

Posted on   PerKins.Zhu  阅读(3604)  评论(0编辑  收藏  举报

===========================================

    原文链接: 动态代理的两种实现方式(JDK/Cglib) 转载请注明出处!

===========================================

什么是代理模式?(设计模式—代理模式)
  代理模式:在调用处不直接调用目标类进行操作,而是调用代理类,然后通过代理类来调用目标类进行操作。在代理类调用目标类的前后可以添加一些预处理和后处理操作来完成一些不属于目标类的功能。
为什么要使用代理模式?
  通过代理模式可以实现对目标类调用的控制、在目标类调用前/后进行一些不属于目标类的操作,如:数据验证、预处理、后处理、异常处理等
什么是静态代理什么是动态代理?
  静态代理:代理类只能实现对”特定接口的实现类“进行代理
  动态代理:代理类可以实现对多种类的代理
jdk代理和cglib代理区别在哪里?
  jdk动态代理:代理所有“实现的有接口”的目标类
     cglib动态代理:代理任意一个目标类,但对final类和方法无法代理
     不同点:jdk动态代理的目标类必须实现的有接口,因为在调用Proxy.newProxyInstance()的时候需要传入目标类的接口类。而cglib不做此限制。    
   

   下面看代码分析:

定义一个Person接口

package com.zpj.designMode.proxy;

//定义一个Person接口
public interface Person {
    public void doWork();
}

 

添加一个实现类:MrLi

复制代码
package com.zpj.designMode.proxy;

//添加一个实现类
public class MrLi implements Person {

    @Override
    public void doWork() {
        System.out.println("-----doWork");
    }

}
复制代码

 

静态代理:

 添加一个静态代理类Proxy

复制代码
package com.zpj.designMode.proxy;

//静态代理,代理必须和目标类实现共同的接口
public class Proxy implements Person {
    private Person person;// 被代理人

    //这里的目标类型决定了该代理类只能代理实现了Person接口的实例,而不能接收其他类型参数,这也就是静态代理的局限性
    public Proxy(Person person) {
        this.person = person;
    }

    @Override
    public void doWork() {
        System.out.println("doSomething-----start");
        person.doWork();
        System.out.println("doSomething-----end");
    }

}
复制代码

 

静态代理测试程序:

复制代码
package com.zpj.designMode.proxy;

public class Run {
    public static void main(String[] args) {
        MrLi li = new MrLi();
        Proxy proxy = new Proxy(li);
        //调用处直接调用代理进行目标方法的操作。
        proxy.doWork();
    }
}
复制代码

 

JDK动态代理:

添加一个代理JDKProxy,该代理实现InvocationHandler接口且覆写invoke方法。

复制代码
package com.zpj.designMode.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/***
 @author  Perkins Zhu
 @date  2017年3月13日 上午8:41:10
 */
public class JDKProxy implements InvocationHandler {

    private Object person;// 被代理人
     
    
    //这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理。但是要注意下面的newProxyInstance()中的参数
    public Object getInstance(Object person) {
        this.person = person;
        //与cglib的区别在于这里构建代理对象的时候需要传入被代理对象的接口对象,第二个参数。而cglib不需要被代理对象实现任何接口即可        
        return Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);
    }



    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("doSomething---------start");
        method.invoke(person, args);
        System.out.println("doSomething---------end");
        return null;
    }

}
复制代码

 

JDK动态代理测试程序

复制代码
package com.zpj.designMode.proxy.jdk;

import com.zpj.designMode.proxy.MrLi;
import com.zpj.designMode.proxy.Person;

/***
 * @author Perkins Zhu
 * @date 2017年3月13日 上午8:51:31
 */
public class Run {

    public static void main(String[] args) {
        Person person = (Person) new JDKProxy().getInstance(new MrLi());
        //注意这里的person不是目标类person,而是代理类person:debug的时候显示null,有'$'标识符
        person.doWork();
    }
}
复制代码

 

Cglib动态代理:

添加一个CglibProxy代理,同时实现MethodInterceptor接口。

复制代码
package com.zpj.designMode.proxy.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/***
 * @author Perkins Zhu
 * @date 2017年3月13日 上午9:02:54
 */
public class CglibProxy implements MethodInterceptor {
    private Object targetObject;

    // 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理
    public Object getInstance(Object target) {
        this.targetObject = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        //注意该处代理的创建过程
        Object proxyObj = enhancer.create();
        return proxyObj;// 返回代理对象
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object obj = null;
        System.out.println("doSomething---------start");
        obj = method.invoke(targetObject, args);
        System.out.println("doSomething---------end");
        return obj;
    }

}
复制代码

 

Cglib动态代理测试程序

复制代码
package com.zpj.designMode.proxy.cglib;

import com.zpj.designMode.proxy.MrLi;
import com.zpj.designMode.proxy.Person;

/***
 @author  Perkins Zhu
 @date  2017年3月13日 上午9:07:38
 */
public class Run {

    public static void main(String[] args) {
        Person person = (Person)new CglibProxy().getInstance(new MrLi());
        person.doWork();
    }
}
复制代码

仔细对比Proxy、CglibProxy和JDKProxy区分静态代理、JDK动态代理和Cglib动态代理的异同点!

 

-------end

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
点击右上角即可分享
微信分享提示