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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java结合Kotlin实现宝宝年龄计算

    Java结合Kotlin实现宝宝年龄计算

    这篇文章主要为大家介绍了Java结合Kotlin实现宝宝年龄计算示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 本地MinIO存储服务Java远程调用上传文件的操作过程

    本地MinIO存储服务Java远程调用上传文件的操作过程

    MinIO是一款高性能、分布式的对象存储系统,它可以100%的运行在标准硬件上,即X86等低成本机器也能够很好的运行MinIO,这篇文章主要介绍了本地MinIO存储服务Java远程调用上传文件的操作过程,需要的朋友可以参考下
    2023-11-11
  • IDEA 2020.2 +Gradle 6.6.1 + Spring Boot 2.3.4 创建多模块项目的超详细教程

    IDEA 2020.2 +Gradle 6.6.1 + Spring Boot 2.3.4 创建多模块项目的超详细教程

    这篇文章主要介绍了IDEA 2020.2 +Gradle 6.6.1 + Spring Boot 2.3.4 创建多模块项目的教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Maven 错误找不到符号的解决方法

    Maven 错误找不到符号的解决方法

    这篇文章主要介绍了Maven 错误找不到符号的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • SpringMVC+MyBatis 事务管理(实例)

    SpringMVC+MyBatis 事务管理(实例)

    本文先分析编程式注解事务和基于注解的声明式事务。对SpringMVC+MyBatis 事务管理的相关知识感兴趣的朋友一起学习吧
    2017-08-08
  • RestTemplate使用Proxy代理作为跳板发送请求

    RestTemplate使用Proxy代理作为跳板发送请求

    这篇文章主要为大家介绍了RestTemplate使用代理proxy作为跳板发送请求的方法示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • Spring boot @RequestBody数据传递过程详解

    Spring boot @RequestBody数据传递过程详解

    这篇文章主要介绍了Spring boot @RequestBody数据传递过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java中如何避免sql注入实例详解

    Java中如何避免sql注入实例详解

    SQL注入是最常见的攻击方式之一,它不是利用操作系统或其它系统的漏洞来实现攻击的,而是程序员因为没有做好判断,被不法用户钻了SQL的空子,下面这篇文章主要给大家介绍了关于Java中如何避免sql注入的相关资料,需要的朋友可以参考下
    2022-01-01
  • 如何手动安装Gradle并配置IDEA使用Gradle构建

    如何手动安装Gradle并配置IDEA使用Gradle构建

    本文给大家分享手动安装Gradle并配置IDEA使用Gradle构建的步骤,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-04-04
  • Java Collection接口中的常用方法总结

    Java Collection接口中的常用方法总结

    这篇文章将大概用代码案例简单总结一下 Collection 接口中的一些方法,我们会以他的实现类 Arraylist 为例创建对象。快一起来看看吧
    2022-12-12

最新评论