JDK代理与CGLib代理

首先我们要先了解什么是代理模式:

​ 代理模式是一种设计模式,它可以为其他对象提供一种代理,以控制对该对象的访问。在现实生活中,代理模式可以用很多例子来说明。下面是一些例子:

  1. 餐厅预订:当你想去一家热门的餐厅用餐时,你可以通过电话或者网络平台预订座位。但是有时候这些餐厅可能会很忙,难以预订。这时,你可以联系一家代理公司,让他们为你预订座位。代理公司会负责与餐厅联系,为你预订座位,并在需要时帮助你修改或取消预订。
  2. 网络购物:当你在购物网站上买东西时,你需要提供个人信息和支付信息。但是有时候你可能不想向这些网站透露太多个人信息。这时,你可以使用一些代理服务,如虚拟信用卡或匿名浏览器插件,来隐藏你的真实身份和信息。
  3. 快递服务:当你需要向远方寄送包裹时,你可以联系快递公司。但是有时候你可能无法直接联系到快递公司,或者需要在特定时间和地点交付包裹。这时,你可以使用一些代理服务,如物流代理公司或快递代收点,来帮助你处理包裹,并在需要时代替你与快递公司联系。

JDK 代理

假设有这样一个场景,我们有一个接口 UserService,其中包含一个方法 save,用于保存用户信息。我们想要在调用这个方法之前,先打印一行日志,表示用户信息正在被保存。我们可以使用 JDK 动态代理来实现这个功能,具体代码如下:

// 被代理对象
public interface UserService {

    void save(String username);
}

public class UserServiceImpl implements UserService{
    @Override
    public void save(String username) {
        System.out.println("Saving user " + username);
    }
}

// 代理对象
public class UserServiceProxy implements InvocationHandler {

    private UserService userService;

    public UserServiceProxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("正在保存用户信息....");
        Object invoke = method.invoke(userService, args);
        System.out.println("成功保存用户信息....");
        return invoke;
    }
}
// 测试
public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        UserService proxyInstance = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, new UserServiceProxy(userService));
        proxyInstance.save("marry");

    }
}

CGLib代理

现在,假设我们有一个类 UserDao,其中包含一个方法 save,用于保存用户信息。我们想要在调用这个方法之前,先打印一行日志,表示用户信息正在被保存。我们可以使用 CGLib 动态代理来实现这个功能

先引入相关依赖

 <dependency>
     <groupId>cglib</groupId>
     <artifactId>cglib</artifactId>
     <version>3.3.0</version>
 </dependency>
// 被代理对象
public class UserDAO {

   public void save(String username) {
      System.out.println("Saving user " + username);
   }
}

// 代理类
public class UserDAOIntercept implements MethodInterceptor {

    // 目标对象,也就是被代理的对象
    private Object target;

    // 通过构造方法进行注入
    public UserDAOIntercept(Object target) {
        this.target = target;
    }

    // 创建代理对象的方法,返回一个代理对象
    public Object getIntercept() {
        // 使用Enhancer类来创建代理对象
        Enhancer enhancer = new Enhancer();
        // 设置父类为目标对象的类
        enhancer.setSuperclass(target.getClass());
        // 设置回调为当前代理类的实例
        enhancer.setCallback(this);
        // 创建并返回代理对象
        return enhancer.create();
    }


    // 实现 MethodInterceptor 接口的 intercept 方法,拦截代理对象的方法调用
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("正在保存用户信息....");
        Object result = methodProxy.invokeSuper(obj, args);
        System.out.println("成功保存用户信息....");
        return result;
    }
}

// 测试
public class Client {

    public static void main(String[] args) {
        // 创建目标对象
        UserDAO userDAO = new UserDAO();
        // 创建代理类,并传入目标对象
        UserDAOIntercept intercept = new UserDAOIntercept(userDAO);
        // 获取代理对象
        UserDAO proxy = (UserDAO) intercept.getIntercept();
        // 调用代理对象的方法
        proxy.save("jack");
    }
}

总结

这两种代理方法的相同点是:

  • 都可以在运行时动态地创建代理对象,而不需要手动编写代理类的代码。
  • 都可以在不修改目标对象的源码的情况下,对目标对象的方法进行增强或拦截。

这两种代理方法的不同点是:

  • JDK 代理需要目标对象实现一个或多个接口,而 CGLib 代理不需要目标对象实现任何接口。
  • JDK 代理是通过实现目标对象的接口来创建代理对象,而 CGLib 代理是通过继承目标对象来创建子类作为代理对象。
  • JDK 代理不能对 final 修饰的类或方法进行代理,而 CGLib 代理可以,但是不能对final修饰的方法进行拦截。
  • JDK 代理的性能比 CGLib 代理的性能稍高,但是 CGLib 代理的功能比 JDK 代理的功能更强大。
  • 由于 CGLib 代理是基于类的代理技术,因此它可以代理非公共的类和方法,而 JDK 动态代理则只能代理公共的类和方法。
  • JDK 动态代理在创建代理对象时,需要传入被代理对象实例和一个实现了 InvocationHandler 接口的回调函数实例,该回调函数将在代理对象方法被调用时执行。而 CGLib 代理则是通过 Enhancer类的 setSuperclass() 方法来指定被代理类,并通过 setCallback() 方法来指定回调函数实例。
  • 由于 JDK 动态代理是基于接口的代理技术,因此它可以为多个接口创建代理对象,而 CGLib 代理只能为一个类创建代理对象
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值