首页 > 编程语言 >Java的动态代理

Java的动态代理

时间:2024-08-17 18:06:10浏览次数:12  
标签:Java 代理 class method helloService 动态 public HelloService

代理模式

代理模式给某一个(目标)对象提供一个代理对象,并由代理对象持有目标对象的引用。所谓代理,就是一个对象代表另一个对象执行相应的动作程序。而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式在实际的生活中场景很多,例如中介、律师、代购等行业,都是简单的代理逻辑,在这个模式下存在两个关键角色:

目标对象角色:即代理对象所代表的对象。
代理对象角色:内部含有目标对象的引用,可以操作目标对象;AOP编程就是基于这个思想。

静态代理

假设我们有一个接口 HelloService,以及它的实现类 HelloServiceImpl:

// 接口
public interface HelloService {
    void sayHello();
}

// 实现类
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("Hello from HelloServiceImpl!");
    }
}

现在我们创建一个静态代理类 HelloServiceProxy,它实现了 HelloService 接口,并持有 HelloServiceImpl 的实例:

public class HelloServiceProxy implements HelloService {
    private HelloService helloService;

    public HelloServiceProxy(HelloService helloService) {
        this.helloService = helloService;
    }

    @Override
    public void sayHello() {
        System.out.println("Before calling sayHello()");
        helloService.sayHello(); // 调用目标对象的方法
        System.out.println("After calling sayHello()");
    }
}

在 HelloServiceProxy 中,我们在调用 sayHello() 方法前后分别添加了一些额外的操作。

现在,我们可以在客户端代码中使用静态代理来调用 HelloService:

public class Main {
    public static void main(String[] args) {
        // 创建目标对象
        HelloService helloService = new HelloServiceImpl();

        // 创建代理对象
        HelloService proxyService = new HelloServiceProxy(helloService);

        // 通过代理对象调用方法
        proxyService.sayHello();
    }
}
Before calling sayHello()
Hello from HelloServiceImpl!
After calling sayHello()

在这个示例中,我们创建了一个 HelloServiceProxy 类来代理 HelloServiceImpl 类。在 sayHello() 方法中,我们在调用目标方法前后添加了一些额外的操作。这种方式可以在不修改目标类的情况下,为目标类添加新的功能。

动态代理

基本使用

在代购刚兴起的初期,是一些常去海外出差的人,会接代购需求,即代理人固定;后来就兴起海外代购平台,海淘等一系列产品,即用户代购需求(目标对象)由代购平台去实现,但是具体谁来操作这个就看即时分配,这个场景与动态代理的原理类似。

// 动态代理的 InvocationHandler 实现
public class HelloServiceInvocationHandler implements InvocationHandler {
    private HelloService helloService;

    public HelloServiceInvocationHandler(HelloService helloService) {
        this.helloService = helloService;
    }

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

public class Main {
    public static void main(String[] args) {
        // 创建目标对象
        HelloService helloService = new HelloServiceImpl();

        // 创建动态代理对象
        HelloService proxyService = (HelloService) Proxy.newProxyInstance(
            helloService.getClass().getClassLoader(),
            new Class[]{HelloService.class},
            new HelloServiceInvocationHandler(helloService)
        );

        // 通过代理对象调用方法
        proxyService.sayHello();
    }
}

进阶特性

我们甚至可以更极端一点,直接不要实现类,直接创建接口的逻辑。

public interface Greeter {
    void greet();
}


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class GreeterProxy {
    public static Greeter createGreeter() {
        Greeter greeter = (Greeter) Proxy.newProxyInstance(
            Greeter.class.getClassLoader(),
            new Class<?>[] { Greeter.class },
            new InvocationHandler() {
                private Logger logger = new Logger();

                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    logger.log("Calling " + method.getName());
                    Object result = method.invoke(this, args);
                    logger.log("Method " + method.getName() + " returned");
                    return result;
                }

                public void greet() {
                    System.out.println("Hello, user!");
                }
            }
        );
        return greeter;
    }
}

同时我们注意,我们是代理类。也就是调用某个动态代理对象的方法时,都会触发代理类的invoke方法,并传递对应的内容。

假设我们有一个 Calculator 接口:

public interface Calculator {
    int add(int a, int b);
    int subtract(int a, int b);
}

然后我们创建一个 CalculatorImpl 类来实现这个接口:

public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int subtract(int a, int b) {
        return a - b;
    }
}

现在,我们来创建一个动态代理类,在 invoke() 方法中添加一些额外的逻辑:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CalculatorProxy {
    public static Calculator createCalculatorProxy() {
        return (Calculator) Proxy.newProxyInstance(
            CalculatorImpl.class.getClassLoader(),
            new Class<?>[] { Calculator.class },
            new CalculatorInvocationHandler(new CalculatorImpl())
        );
    }

    private static class CalculatorInvocationHandler implements InvocationHandler {
        private final Calculator calculator;

        public CalculatorInvocationHandler(Calculator calculator) {
            this.calculator = calculator;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 在调用目标方法前记录日志
            System.out.println("Calling method: " + method.getName());

            // 调用目标方法
            Object result = method.invoke(calculator, args);

            // 在调用目标方法后记录日志
            System.out.println("Method " + method.getName() + " returned: " + result);

            return result;
        }
    }
}
Calculator calculatorProxy = CalculatorProxy.createCalculatorProxy();
int result = calculatorProxy.add(5, 3);
System.out.println("Result: " + result);

参考链接

https://cloud.tencent.com/developer/article/1843361

标签:Java,代理,class,method,helloService,动态,public,HelloService
From: https://www.cnblogs.com/Ho1dF0rward/p/18364748

相关文章

  • java+vue计算机毕设基于Web的在线考试管理信息系统【源码+开题+论文】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展和教育改革的不断深入,传统考试模式已难以满足现代教育的需求。在线考试作为一种新兴的教育评估方式,凭借其便捷性、高效性和灵......
  • 基于ssm的新生报到系统(有报告)。Javaee项目,ssm项目。
    演示视频:基于ssm的新生报到系统(有报告)。Javaee项目,ssm项目。资源下载:基于ssm的新生报到系统(有报告)。Javaee项目,ssm项目。项目介绍:采用M(model)V(view)C(controller)三层体系结构,通过Spring+SpringMvc+Mybatis+Jsp+Maven来实现。MySQL数据库作为系统数据储存......
  • 基于ssm的在线医疗服务系统(有报告)。Javaee项目,ssm项目。
    演示视频:基于ssm的在线医疗服务系统(有报告)。Javaee项目,ssm项目。资源下载:基于ssm的在线医疗服务系统(有报告)。Javaee项目,ssm项目。项目介绍:采用M(model)V(view)C(controller)三层体系结构,通过Spring+SpringMvc+Mybatis+Jsp+Maven来实现。MySQL数据库作为系统......
  • 【Java毕设选题推荐】基于SpringBoot的springboot基于Android的房屋租赁App
    前言:我是IT源码社,从事计算机开发行业数年,专注Java领域,专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务......
  • Java数据库框架设计
    什么是ORM?ORM(Object-RelationalMapping)表示对象关系映射。在面向对象的软件开发中,通过ORM,就可以把对象映射到关系型数据库中。只要有一套程序能够做到建立对象与数据库的关联,操作对象就可以直接操作数据库数据,就可以说这套程序实现了ORM对象关系映射简单的说:ORM就是建立实体......
  • Java的Spi
    什么是SPI?SPI全称:ServiceProviderInterface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需......
  • JAVA数据库
    基础概念ORM框架ORM框架是一种技术,用于在面向对象的编程语言(如Java)和关系型数据库之间建立映射关系。ORM框架允许开发者使用面向对象的方式操作数据库,而不需要直接编写SQL语句。JPAJPA是一种Java持久化API规范,定义了一套标准的Java持久化API。JPA规......
  • 【免费】ssm驾校预约管理系统jsp|毕业设计|Javaweb项目
    收藏点赞不迷路 关注作者有好处编号:ssm560ssm驾校预约管理系统jsp开发语言:Java数据库:MySQL技术:Spring+SpringMVC+MyBatis+Vue工具:IDEA/Ecilpse、Navicat、Maven1.系统展示2.万字文档展示第5章系统详细设计系统实现这个章节的内容主要还是展示系统的功能界面设计......
  • 【免费】ssm公交车信息管理系统|毕业设计|Javaweb项目
    收藏点赞不迷路 关注作者有好处编号:ssm572ssm公交车信息管理系统开发语言:Java数据库:MySQL技术:Spring+SpringMVC+MyBatis+Vue工具:IDEA/Ecilpse、Navicat、Maven 1.系统展示2.万字文档展示第5章系统详细设计3.5.1个人中心通过设计的个人中心功能模块,用户可以......
  • 【免费】ssm基于JavaEE的仓库管理系统设计与开发|毕业设计|Javaweb项目
    收藏点赞不迷路 关注作者有好处编号:ssm500ssm基于JEE的仓库管理系统设计与开发开发语言:Java数据库:MySQL技术:Spring+SpringMVC+MyBatis+Vue工具:IDEA/Ecilpse、Navicat、Maven文末获取源码1.系统展示2.万字文档展示第5章系统实现编程人员在搭建的开发环境中,运用......