Java动态代理

目录

1.什么是动态代理?

2.动态代理和静态代理的区别

3.使用场景

4.Java 中的动态代理机制

5.实现动态代理的步骤

6.动态代理的局限性

7.代码示例


1.什么是动态代理?

动态代理(Dynamic Proxy)是指在运行时动态生成代理类及其对象的机制,它允许在运行时创建代理对象并将方法调用转发给被代理对象。

2.动态代理和静态代理的区别

  • 静态代理是在编译时指定代理对象,代理对象和被代理对象之间的关系是固定的。
  • 动态代理是在运行时动态生成代理对象,代理对象和被代理对象之间的关系可以在运行时改变。

3.使用场景

  1. 动态代理:代理类是通过Java提供的反射机制动态生成的,不需要编写具体的代理类,只需提供接口定义和一个InvocationHandler接口的实现类,通过反射的方式,在运行时动态生成代理类并处理方法调用。
  2. 虚拟代理(Virtual Proxy):当需要延迟加载对象,减少资源占用或提高性能时,可以使用动态代理来创建一个虚拟代理。虚拟代理在访问对象之前进行实例化,并在需要时才加载真正的对象。

  3. 安全代理(Protection Proxy):当需要对方法进行安全性检查或权限验证时,可以使用动态代理来创建一个安全代理,控制对实际对象的访问。安全代理可以在调用实际对象之前进行权限验证,并决定是否执行方法调用。

  4. 日志记录(Logging):当需要在方法调用前后记录日志信息时,可以使用动态代理来创建一个代理对象,在方法调用前后记录相关的日志信息。这样可以对系统的运行进行监控、调试和分析。

  5. AOP(Aspect-Oriented Programming):AOP是一种面向切面编程的技术,可以使用动态代理来实现AOP中的横切关注点(cross-cutting concerns)。通过动态代理,可以将横切关注点的代码和业务逻辑代码分离,实现更好的模块化和可维护性。

4.Java 中的动态代理机制

  • java.lang.reflect.Proxy:该类用于生成动态代理对象。
  • java.lang.reflect.InvocationHandler接口:该接口定义了代理对象的调用处理程序,通过实现该接口可以自定义代理对象的行为。

5.实现动态代理的步骤

  • 创建一个实际的对象,即被代理对象。
  • 创建一个实现 InvocationHandler 接口的调用处理程序,用于在代理对象的方法被调用时执行相应的逻辑。
  • 使用 Proxy.newProxyInstance() 方法创建一个动态代理对象,该方法接收类加载器、接口数组和调用处理程序作为参数。
  • 通过动态代理对象调用相应的方法来触发代理动作,代理对象会将方法调用委托给调用处理程序。

6.动态代理的局限性

  • 代理对象只能代理实现了接口的对象,无法代理没有实现接口的对象。
  • 被代理对象的非公共方法无法被代理,因为代理对象只能调用公共的方法。

7.代码示例

// 定义明星接口
interface Star {
    void perform();
}

// 实现明星接口的大明星类
class TomCruise implements Star {
    @Override
    public void perform() {
        System.out.println("Tom Cruise is performing!");
    }
}

// 实现InvocationHandler接口的代理类
class Agent implements InvocationHandler {
    private Object target; // 被代理的目标对象

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Agent: Before method: " + method.getName());
        Object result = method.invoke(target, args); // 调用目标对象的方法
        System.out.println("Agent: After method: " + method.getName());
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        TomCruise tomCruise = new TomCruise(); // 实例化大明星对象

        Agent agent = new Agent(tomCruise); // 创建代理对象,传入大明星对象

        // 创建动态代理对象,该代理对象实现了Star接口,调用处理程序为Agent对象
        Star proxy = (Star) Proxy.newProxyInstance(
                tomCruise.getClass().getClassLoader(), // 类加载器
                tomCruise.getClass().getInterfaces(), // 实现的接口数组
                agent); // 调用处理程序

        proxy.perform(); // 通过动态代理对象调用perform()方法
    }
}

在上面的示例中,我们首先定义了一个明星接口 Star,其中有一个 perform() 方法用于表演。

然后我们创建了一个名为 TomCruise 的大明星类,实现了 Star 接口,并且在 perform() 方法中输出了相应的信息。

接着,我们创建了一个叫做 Agent 的代理类,它实现了 InvocationHandler 接口,用于代理 TomCruise 的工作。在 invoke() 方法中,我们在方法调用前后添加了一些额外的逻辑。

在 Main 类的 main() 方法中,我们创建了一个 TomCruise 对象和一个 Agent 对象,并将 Agent 对象传递给 Proxy.newProxyInstance() 方法来生成一个动态代理对象。

最后,我们通过动态代理对象 proxy 来调用 perform() 方法,代理对象将会执行 Agent 类中定义的前置和后置处理逻辑,并最终调用 TomCruise 中的 perform() 方法。

执行上述代码后,你将会看到如下输出:

Agent: Before method: perform
Tom Cruise is performing!
Agent: After method: perform

这个示例展示了一个大明星 TomCruise 和他的代理经纪人 Agent 的使用动态代理的场景。在代理对象的方法调用前后,代理经纪人可以添加额外的逻辑,比如在表演前进行准备工作或者在表演后进行收尾工作。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值