当前位置: 首页 > article >正文

Proxy与CGLib代理:深入解析与应用

### Proxy与CGLib代理:深入解析与应用

在软件开发中,代理模式是一种常见的设计模式,通过代理对象控制对目标对象的访问,增强目标对象的功能。在Java开发中,Proxy和CGLib是两种常用的代理实现方式,它们在应用场景、实现原理以及性能表现上各有特色。本文将深入解析Proxy和CGLib代理的原理,并通过示例展示它们在实际开发中的应用。

#### Proxy代理

Proxy代理基于Java的反射机制,通过动态生成代理类实现对目标对象的代理。Proxy代理要求目标对象必须实现至少一个接口,代理类将实现与目标对象相同的接口,并在方法调用时通过反射机制调用目标对象的方法。

**实现步骤**:

1. 定义一个接口,并创建目标对象实现该接口。
2. 创建一个实现了`InvocationHandler`接口的代理类,在`invoke`方法中编写代理逻辑。
3. 使用`Proxy.newProxyInstance`方法生成代理对象,并将目标对象和代理类传递给该方法。

**示例**:

```java
public interface IUserDao {
    void save();
    void delete();
}

public class UserDao implements IUserDao {
    public void save() {
        System.out.println("====save");
    }
    public void delete() {
        System.out.println("====delete");
    }
}

public class ProxyFactory {
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("Before method " + method.getName() + " invoke");
                    Object result = method.invoke(target, args);
                    System.out.println("After method " + method.getName() + " invoke");
                    return result;
                }
            }
        );
    }
}

public class Client {
    public static void main(String[] args) {
        IUserDao target = new UserDao();
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
        proxy.save();
        proxy.delete();
    }
}
```

**优点**:

- 代理对象与目标对象实现了相同的接口,易于扩展和维护。
- 可以在不修改目标对象代码的情况下,增加额外的功能。

**缺点**:

- 目标对象必须实现接口,无法代理没有接口的类。
- 反射机制会增加一定的性能开销。

#### CGLib代理

CGLib(Code Generation Library)是一个高性能的代码生成库,可以在运行时生成Java类的字节码。CGLib代理通过生成目标类的子类来实现代理功能,因此不需要目标对象实现接口。

**实现步骤**:

1. 创建一个目标类。
2. 创建一个实现了`MethodInterceptor`接口的代理类,在`intercept`方法中编写代理逻辑。
3. 使用CGLib的`Enhancer`类生成代理对象,并将目标对象和代理类传递给`Enhancer`类。

**示例**:

```java
public class TargetClass {
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

public class MyInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method " + method.getName() + " invoke");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method " + method.getName() + " invoke");
        return result;
    }
}

public class CGLibProxy {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(TargetClass.class);
        enhancer.setCallback(new MyInterceptor());
        TargetClass proxy = (TargetClass) enhancer.create();
        proxy.doSomething();
    }
}
```

**优点**:

- 可以代理没有接口的类,更加灵活。
- 性能相对较高,因为直接调用子类的方法,减少了反射的开销。

**缺点**:

- 无法代理final类和方法,因为CGLib是通过继承实现代理的。
- 生成的子类字节码较大,可能会影响加载和运行时性能。

#### 应用场景

- **Proxy代理**:适用于目标对象实现了接口的场景,如Spring框架中的AOP(面向切面编程)实现。
- **CGLib代理**:适用于目标对象没有实现接口的场景,如需要对类的方法进行增强或监控。


 


http://www.kler.cn/a/420739.html

相关文章:

  • 在办公室环境中用HMD替代传统显示器的优势
  • brew安装mongodb和php-mongodb扩展新手教程
  • Leetcode62. 不同路径(HOT100)
  • C# 集合(Collection)
  • 卷积神经网络(CNN)的层次结构
  • THENA大涨将对整个DeFi市场产生怎样的影响?
  • 5.vue3+openlayers加载ArcGIS地图示例
  • Kafka 图形化工具 Eagle安装
  • ios上滚动条不能滑动 滚动卡住的问题
  • HTTP协议详解:从HTTP/1.0到HTTP/3的演变与优化
  • 在超表面中琼斯矩阵的使用
  • vue3+element-plus多选框全选与单选
  • matlab 中的 bug
  • K8S控制台kubernetes-dashboard快速安装
  • RHCE: SELinux
  • 力扣第81题 搜索旋转排序数组 II
  • SHELL脚本2(Linux网络服务器 23)
  • 如何运用Java爬虫获得1688商品详情数据
  • 架构03-事务处理
  • YunSDR通信小课堂-10
  • 扩展欧几里得——acwing
  • dify接入ollama模型报错:max retries exceeded with url
  • Java的反射(Reflection)
  • AWTK fscript 中的 串口 扩展函数
  • Linux:systemd进程管理【1】
  • 如何在vue中禁用eslint检查?