Spring中的代理ProxyFactory解析

 更新时间:2023年12月25日 11:43:51   作者:努力中的少年  
这篇文章主要介绍了Spring中的ProxyFactory解析,在Java中,代理模式的实现通常依靠Proxy类和InvocationHandler接口,本文将介绍如何使用ProxyFactory来创建代理模式,需要的朋友可以参考下

前言

当涉及到Java程序员们谈论面向对象编程的时候,代理模式总是一个热门话题。代理模式在许多场景下都有用武之地,比如日志记录、事务管理、权限验证等等。

而在Java中,代理模式的实现通常依靠Proxy类和InvocationHandler接口。本文将介绍如何使用ProxyFactory来创建代理模式。

什么是代理模式?

在计算机科学中,代理模式是一种结构型设计模式,它可以为其他对象提供一个替代品或者占位符,以控制对这个对象的访问。

代理对象通常充当了客户端和目标对象之间的中介,从而可以隐藏目标对象的实现细节、保护目标对象不被非法访问、增强目标对象的功能等等。

代理模式有两种形式:静态代理和动态代理。静态代理的优点是能够提前做好一些工作,例如参数的检查、日志记录等等;

缺点则是需要针对每个需要代理的接口编写一个代理类。而动态代理则可以根据接口生成代理对象,并且可以在运行时动态的添加和修改代理方法,因此更加灵活。

了解Proxy和InvocationHandler

在Java中,代理模式的实现主要依靠了Proxy类和InvocationHandler接口。其中,Proxy类是生成代理类的主要工具,而InvocationHandler则是提供对代理方法的具体实现。

Proxy类有两个静态方法可以用来创建代理对象:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

该方法用于创建一个动态代理对象,参数loader表示ClassLoader、interfaces表示实现的接口列表、h表示InvocationHandler。

public static Object newProxyInstance(Class<?> clazz, InvocationHandler h)

该方法用于创建一个指定类的代理对象,参数clazz表示需要代理的类、h表示InvocationHandler。

而InvocationHandler接口则是定义了一个统一的代理方法:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

在代理模式中,当我们调用代理对象的方法时,实际上会调用InvocationHandler的invoke()方法,在这个方法中,我们可以根据需要进行一些操作,并返回目标对象的执行结果。

使用ProxyFactory创建动态代理

在Java中,如果要使用动态代理,首先需要创建一个InvocationHandler实现类。例如,下面是一个简单的InvocationHandler实现类:

public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before calling " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("After calling " + method.getName());
        return result;
    }
}

这个InvocationHandler实现类接受一个代理对象的目标对象,然后在代理方法被调用前输出一行日志,在返回结果之前再输出一行日志。

然后我们可以通过ProxyFactory来创建一个动态代理对象。ProxyFactory是一个通用的代理工厂,它提供了很多便捷的方法来创建不同类型的代理。例如下面的代码演示了如何使用ProxyFactory来创建一个JDK动态代理:

public class ProxyTest {
    public static void main(String[] args) {
        // 创建目标对象
        HelloService helloService = new HelloServiceImpl();
        // 创建InvocationHandler实例
        InvocationHandler invocationHandler = new MyInvocationHandler(helloService);
        // 创建代理对象
        HelloService proxy = (HelloService) ProxyFactory.getProxy(helloService.getClass, invocationHandler);
    // 调用代理对象的方法
    proxy.sayHello("Jack");
}
}

在上面的代码中,我们首先创建了一个目标对象HelloServiceImpl。然后创建了一个InvocationHandler实例,并将HelloServiceImpl作为它的参数传递进去。最后通过调用ProxyFactory的getProxy()方法来生成一个动态代理对象proxy。在调用proxy的sayHello()方法时,实际上会调用MyInvocationHandler的invoke()方法,在这个方法中输出日志并调用HelloServiceImpl的sayHello()方法,最终返回结果。

使用ProxyFactory创建Cglib动态代理

除了JDK动态代理之外,还有一种常见的动态代理实现方式是使用Cglib库。与JDK动态代理不同,Cglib动态代理可以代理非接口类型的类。

下面我们演示如何使用ProxyFactory来创建一个Cglib动态代理:

public class ProxyTest {
    public static void main(String[] args) {
        // 创建目标对象
        UserDaoImpl userDao = new UserDaoImpl();
        // 创建MethodInterceptor实例
        MethodInterceptor methodInterceptor = new MyMethodInterceptor(userDao);
        // 创建代理对象
        UserDaoImpl proxy = (UserDaoImpl) ProxyFactory.getProxy(userDao.getClass(), methodInterceptor);
        // 调用代理对象的方法
        proxy.save();
    }
}
class UserDaoImpl {
    public void save() {
        System.out.println("Saving user...");
    }
}
class MyMethodInterceptor implements MethodInterceptor {
    private Object target;
    public MyMethodInterceptor(Object target) {
        this.target = target;
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before calling " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("After calling " + method.getName());
        return result;
    }
}

在这个例子中,我们创建了一个UserDaoImpl类,并为它创建了一个MethodInterceptor实现类。

然后通过调用ProxyFactory的getProxy()方法来生成一个Cglib动态代理对象proxy。

在调用proxy的save()方法时,实际上会调用MyMethodInterceptor的intercept()方法,在这个方法中输出日志并调用UserDaoImpl的save()方法,最终返回结果。

总结

本文介绍了如何使用ProxyFactory来创建动态代理,包括JDK动态代理和Cglib动态代理。

通过使用ProxyFactory,可以更加方便地创建代理对象,并且可以根据需要自定义不同类型的代理行为。

虽然动态代理不是解决所有问题的万能工具,但在某些场景下,它仍然是一种非常强大和有用的设计模式。

到此这篇关于Spring中的代理ProxyFactory解析的文章就介绍到这了,更多相关Spring的ProxyFactory内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot项目中HTTP请求体只能读一次的解决方案

    SpringBoot项目中HTTP请求体只能读一次的解决方案

    在基于Spring开发Java项目时,可能需要重复读取HTTP请求体中的数据,例如使用拦截器打印入参信息等,但当我们重复调用getInputStream()或者getReader()时,通常会遇到SpringBoot HTTP请求只读一次的问题,本文给出了几种解决方案,需要的朋友可以参考下
    2024-08-08
  • java实现监听u盘示例分享

    java实现监听u盘示例分享

    这篇文章主要介绍了java实现监听u盘示例,需要的朋友可以参考下
    2014-03-03
  • java 查询oracle数据库所有表DatabaseMetaData的用法(详解)

    java 查询oracle数据库所有表DatabaseMetaData的用法(详解)

    下面小编就为大家带来一篇java 查询oracle数据库所有表DatabaseMetaData的用法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • 使用Jenkins来构建GIT+Maven项目的方法步骤

    使用Jenkins来构建GIT+Maven项目的方法步骤

    这篇文章主要介绍了使用Jenkins来构建GIT+Maven项目,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • ExecutorService实现获取线程返回值

    ExecutorService实现获取线程返回值

    这篇文章主要介绍了ExecutorService实现获取线程返回值,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • Idea Jrebel 报错:Cannot reactivate,offline seat in use

    Idea Jrebel 报错:Cannot reactivate,offline 

    本文主要介绍了Idea Jrebel 报错:Cannot reactivate,offline seat in use,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • Java实现一个简单的长轮询的示例代码

    Java实现一个简单的长轮询的示例代码

    长轮询是与服务器保持即时通信的最简单的方式,它不使用任何特定的协议,例如 WebSocket ,所以也不依赖于浏览器版本等外部条件的兼容性。本文将用Java实现一个简单的长轮询,需要的可以参考一下
    2022-08-08
  • Java设计模式之策略模式示例详解

    Java设计模式之策略模式示例详解

    策略模式属于Java 23种设计模式中行为模式之一,该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。本文将通过示例详细讲解这一模式,需要的可以参考一下
    2022-03-03
  • Mybatis order by 动态传参出现的问题及解决方法

    Mybatis order by 动态传参出现的问题及解决方法

    今天,我正在愉快地CRUD,突然发现出现一个Bug,我们来看看是怎么回事吧!接下来通过本文给大家介绍Mybatis order by 动态传参出现的一个小bug,需要的朋友可以参考下
    2021-07-07
  • Java实现字符串反转的常用方法小结

    Java实现字符串反转的常用方法小结

    在Java中,你可以使用多种方法来反转字符串,这篇文章主要为大家整理了几种常见的反转字符串的方法,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03

最新评论