JDK代理、CGLIB代理及静态代理
发布日期:2021-04-30 21:00:27 浏览次数:171 分类:精选文章

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

代理模式详解

代理模式定义

在软件设计中,代理模式是一种常用的设计模式。其核心思想是:通过引入一个代理类,间接地代理目标对象的操作。代理类与被代理类(目标对象)通常都实现同一个接口或继承自同一个基类。代理类中存有指向被代理类的引用。当通过代理类的方法调用时,实际执行的是被代理类对应的方法。

代理的分类

代理模式可根据实现方式分为以下几种:

  • 静态代理

    静态代理是软件开发中最常用的代理形式。在代码中显式地定义了代理类。这种方式通常用于需求明确、结构清晰的场景。

  • JDK代理

    JDK动态代理(Java Development Kit Proxy)是基于Java反射机制实现的动态代理。其特点是只能对实现了Java接口的类生成代理,而不能针对类本身。

  • CGLIB代理

    CGLIB(Code Generation Library)代理是基于ASM字节码生成框架实现的动态代理。它通过动态生成目标类的子类来实现代理功能。这种方式适用于需要对类进行继承处理的情况。

  • 代码实现

    整体代码目录结构

    以下是完整代码实现示例:

    com/  xszr/    proxy/      static/        ICount.java        CountImpl.java        CountProxyImpl.java        StaticMain.java      jdk/        ICount.java        CountImpl.java        MyInvocationHandler.java        JDKMain.java      cglib/        ICount.java        CountImpl.java        CountImplCglib.java        CGLIBMain.java

    静态代理实现

    ICount.java

    package com.xzsyr.statiz.proxy;public interface ICount {    void queryCount();}

    CountImpl.java

    package com.xzsyr.statiz.proxy;public class CountImpl implements ICount {    @Override    public void queryCount() {        System.out.println("我是queryCount方法。");    }}

    CountProxyImpl.java

    package com.xzsyr.statiz.proxy;public class CountProxyImpl implements ICount {    private CountImpl count;    public CountProxyImpl(CountImpl count) {        super();        this.count = count;    }    @Override    public void queryCount() {        System.out.println("事务处理前.....");        count.queryCount();        System.out.println("事务处理后.....");    }}

    StaticMain.java

    package com.xzsyr.statiz.proxy;public class StaticMain {    public static void main(String[] args) {        CountImpl c = new CountImpl();        CountProxyImpl p = new CountProxyImpl(c);        p.queryCount();    }}

    JDK代理实现

    ICount.java

    package com.xzsyr.jdkdy.proxy;public interface ICount {    void queryCount();}

    CountImpl.java

    package com.xzsyr.jdkdy.proxy;public class CountImpl implements ICount {    @Override    public void queryCount() {        System.out.println("我是queryCount方法");    }}

    MyInvocationHandler.java

    package com.xzsyr.jdkdy.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler {    private CountImpl countImpl;    public MyInvocationHandler(CountImpl countImpl) {        this.countImpl = countImpl;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("事务处理前。。。。");        method.invoke(countImpl, args);        System.out.println("事务处理后。。。。");        return null;    }}

    JDKMain.java

    package com.xzsyr.jdkdy.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class JDKMain {    public static void main(String[] args) {        CountImpl count = new CountImpl();        count.queryCount();        System.out.println("==========================================");        InvocationHandler hander = new MyInvocationHandler(count);        ICount proxyInstance = (ICount) Proxy.newProxyInstance(count.getClass().getClassLoader(), count.getClass().getInterfaces(), hander);        proxyInstance.queryCount();    }}

    CGLIB代理实现

    ICount.java

    package com.xzsyr.cglibdy.proxy;public class ICount {    public void queryCount() {        System.out.println("账户类查询方法");    }}

    CountImpl.java

    package com.xzsyr.cglibdy.proxy;public class CountImpl {    public void quryCount() {        System.out.println("查询querycount方法");    }}

    CountImplCglib.java

    package com.xzsyr.cglibdy.proxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CountImplCglib implements MethodInterceptor {    private Object target;    public Object getInstance(Object target) {        this.target = target;        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(target.getClass());        enhancer.setCallback(this);        return enhancer.create();    }    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("预处理——————");        proxy.invokeSuper(obj, args);        System.out.println("调用后操作——————");        return null;    }}

    CGLIBMain.java

    package com.xzsyr.cglibdy.proxy;public class CGLIBMain {    public static void main(String[] args) {        CountImpl c = new CountImpl();        CountImplCglib cglib = new CountImplCglib();        CountImpl ccglib = (CountImpl) cglib.getInstance(c);        ccglib.quryCount();    }}

    代理模式的选择依据

    在实际应用中,选择使用哪种代理方式取决于具体需求:

  • 静态代理 vs 动态代理

    • 静态代理:显式定义代理类,适合需求明确且结构清晰的场景。
    • 动态代理:通过反射或字节码生成动态生成代理类,适合需求变化多端、对具体实现细节不敏感的场景。
  • JDK代理 vs CGLIB代理

    • JDK代理:适用于目标对象实现了接口的情况。
    • CGLIB代理:适用于目标对象是具体类且需要继承处理的情况。
  • Spring的选择依据

    • Spring默认会根据目标Bean是否实现接口选择JDK或CGLIB代理。
    • 可以通过配置强制使用CGLIB代理:
  • CGLIB的使用注意事项

    • 依赖包

      使用CGLIB时,需要引入以下依赖:

      net.sf.cglib
      cglib
      3.1
      org.ow2.asm
      asm
      5.0.4
    • 错误处理

      如果在非Maven项目中使用CGLIB,需要手动引入cglib.jarasm.jar文件。

    • 性能对比

      相比JDK代理,CGLIB的性能略低,但在高并发场景下表现更优。

    上一篇:怎么在百度里通过关键词搜索到自己的网站
    下一篇:JavaWeb学习笔记(4)__正则表达式

    发表评论

    最新留言

    路过按个爪印,很不错,赞一个!
    [***.219.124.196]2026年06月05日 05时07分19秒