首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【愚公系列】2023年10月 Java教学课程 089-Proxy动态代理

【愚公系列】2023年10月 Java教学课程 089-Proxy动态代理

作者头像
愚公搬代码
发布2025-05-28 15:14:43
发布2025-05-28 15:14:43
10600
代码可运行
举报
文章被收录于专栏:历史专栏历史专栏
运行总次数:0
代码可运行

🚀前言

动态代理是指在程序运行时动态地创建一个代理对象,代理对象可以替代被代理者进行一些操作,而且可以在不改变被代理者的情况下扩展代理对象的功能。

在编程语言中,动态代理是使用反射机制来实现的。通常情况下,代理对象是实现了与被代理对象相同的接口的一个类。通过调用代理对象的方法,代理对象会在调用被代理对象的方法之前或之后加入一些逻辑,从而实现对被代理对象的控制和扩展。

动态代理在实际应用中非常广泛,例如在AOP(面向切面编程)中常用于对方法进行添加切面逻辑;在RPC(远程过程调用)中可用于实现远程方法调用;在ORM(对象关系映射)中可用于实现对数据库操作的封装等等。

🚀一、Proxy动态代理

🔎1.概念

在Java中,动态代理是一种运行时创建代理对象的机制,代理对象的行为由代理类动态生成,并在运行时被指定。动态代理会自动将所有接口方法的调用分派到一个处理器(InvocationHandler)上。处理器负责将方法调用转发给实际对象,并可以进行一些预处理或后处理操作。

Proxy类是Java标准库中的一个类,用于创建代理对象。通过Proxy类,我们可以使用Java动态代理机制创建一个实现指定接口的动态代理类对象。

在使用动态代理时,需要先定义一个接口,该接口包含需要代理的方法。然后创建一个InvocationHandler对象实现对代理方法的处理。最后使用Proxy类的静态方法newProxyInstance()生成代理对象。

动态代理常用于AOP(面向切面编程)和RPC(远程过程调用)等场景中。

🔎2.方法

方法名

返回值类型

描述

newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

Object

创建一个实现指定接口的代理对象

isProxyClass(Class<?> cl)

booleam

判断一个类是否是动态代理类

getProxyClass(ClassLoader loader, Class<?>… interfaces)

Class<?>

获取指定接口的动态代理类

示例:

代码语言:javascript
代码运行次数:0
运行
复制
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface IUserManager {
    void addUser(String username, String password);
}

class UserManager implements IUserManager {

    @Override
    public void addUser(String username, String password) {
        System.out.println("添加用户:" + username + ", 密码:" + password);
    }
}

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("正在执行方法 " + method.getName() + "...");
        return method.invoke(target, args);
    }
}

public class Main {
    public static void main(String[] args) {
        IUserManager userManager = new UserManager();
        MyInvocationHandler invocationHandler = new MyInvocationHandler(userManager);
        IUserManager userManagerProxy = (IUserManager)Proxy.newProxyInstance(
            userManager.getClass().getClassLoader(),
            userManager.getClass().getInterfaces(),
            invocationHandler);
        userManagerProxy.addUser("admin", "123456");
    }
}

输出结果:

代码语言:javascript
代码运行次数:0
运行
复制
正在执行方法 addUser...
添加用户:admin, 密码:123456

🔎3.案例

代码语言:javascript
代码运行次数:0
运行
复制
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface IUserManager {
    void addUser(String username, String password);

    void deleteUser(String username);
}

class UserManager implements IUserManager {

    @Override
    public void addUser(String username, String password) {
        System.out.println("添加用户:" + username + ", 密码:" + password);
    }

    @Override
    public void deleteUser(String username) {
        System.out.println("删除用户:" + username);
    }
}

class LoggerImpl implements InvocationHandler {

    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置日志");
        Object result = method.invoke(target, args);
        System.out.println("后置日志");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        IUserManager userManager = new UserManager();
        LoggerImpl loggerImpl = new LoggerImpl(userManager);
        IUserManager userManagerProxy = (IUserManager)Proxy.newProxyInstance(
            userManager.getClass().getClassLoader(),
            userManager.getClass().getInterfaces(),
            loggerImpl);
        userManagerProxy.addUser("admin", "123456");
        userManagerProxy.deleteUser("testUser");
    }
}

输出结果:

代码语言:javascript
代码运行次数:0
运行
复制
前置日志
添加用户:admin, 密码:123456
后置日志
前置日志
删除用户:testUser
后置日志

在这个例子中,我们使用动态代理添加了日志功能,通过调用Proxy.newProxyInstance()方法,创建了一个IUserManager接口的代理对象userManagerProxy,并在LoggerImpl类中实现了前置日志和后置日志的输出。当我们调用userManagerProxy的方法时,实际上是调用了invoke()方法,在该方法中处理了前置日志、调用实际对象的方法以及后置日志。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🚀前言
  • 🚀一、Proxy动态代理
    • 🔎1.概念
    • 🔎2.方法
    • 🔎3.案例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档