今天学习Java的动态代理,我们来探讨动态代理的概念和应用。
二、内容2.1 简介(1)什么是动态代理动态代理是Java中一种强大的编程机制,它允许我们在运行时创建代理对象,以代替直接访问对象。通常,动态代理用于实现横切关注点(cross-cutting concerns),如日志记录、事务管理和权限控制等,而无需修改原始类的代码。换句话说,动态代理能够以无侵入的方式为类的方法添加其他功能。代理类在其方法中调用目标类的方法,并可以在调用前后添加额外的逻辑。
(2)为什么需要动态代理Java中的动态代理主要依赖于Java的反射机制和代理对象的InvocationHandler接口。
(3)动态代理 vs 静态代理Java中的动态代理主要使用两个核心类来实现:java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler。动态代理不需要为每个目标类编写一个代理类,而是在运行时生成代理对象。
Proxy类:通过Proxy.getProxyClass方法生成代理类的Class对象,然后通过反射机制创建代理对象。 InvocationHandler:代理对象的方法调用会委托给InvocationHandler对象来处理。 newProxyInstance方法:Proxy类提供了newProxyInstance方法,可以直接生成代理对象,隐藏了代理类的生成细节。
静态代理通常需要为每个目标类编写一个代理类,将前后逻辑添加到代理类中,然后在客户端使用代理类来间接调用目标类的方法以实现功能增强。然而,这种方法存在一些缺点,如高维护成本、对接口的依赖和对大规模项目的不适用。
与之相比,动态代理的优势包括:
动态代理在多个领域中广泛应用,提供了一种灵活且非侵入性的方式来实现功能增强和控制。一些应用场景包括:
在Java中,动态代理对象通常使用Proxy.newProxyInstance方法创建。
java
复制代码
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler)
可以看到,这个方法接受三个参数:
InvocationHandler是一个函数式接口,它包含一个invoke方法,用于处理代理对象方法的调用。在invoke方法中,你可以添加自定义的逻辑,如在方法执行前后执行额外的操作。
java
复制代码
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
在invoke方法中,可以根据method参数中的方法信息和args参数中的参数来自定义方法的执行逻辑,例如在方法执行前后添加额外的操作。invoke方法的返回值应该与被代理方法的返回值类型相匹配,并需要处理可能抛出的Throwable异常。
2.3 示例(1)需求假设我们有一个明星接口 Star,其中定义了明星可以唱歌和跳舞的方法。我们还有一个具体的明星类 BigStar,它实现了 Star 接口。现在,我们希望使用动态代理来创建一个代理对象,控制对 BigStar 对象方法的访问,同时在方法执行前后添加额外的操作。
(2)明星接口和大明星类我们将创建一个经纪人来代理明星,以便在明星的行为前后添加一些额外的功能。
首先,我们有一个明星接口 Star,它定义了明星的行为,包括唱歌、跳舞和说唱。接着,我们有一个实现了 Star 接口的大明星类 BigStar,它可以执行这些行为。
java
复制代码
/** * 明星接口: 唱跳rap */ interface Star { // 唱歌 void sing(String name); // 跳舞 void dance(); // rap void rap(); } /** * 大明星:能唱能跳能rap */ class BigStar implements Star { private String name; public BigStar(String name) { this.name = name; } // 唱歌 @Override public void sing(String name){ System.out.println(this.name "正在唱" name); } // 跳舞 @Override public void dance(){ System.out.println(this.name "正在跳舞"); } @Override public void rap() { System.out.println(this.name "正在说唱"); } // ... 其他方法和属性 }
(3)动态代理增强功能现在,我们将创建一个经纪人类 DynamicProxy,并使用动态代理来为大明星增强功能。经纪人将在大明星的行为前后添加额外的功能。
java
复制代码
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxy { public static void main(String[] args) { // 1. 创建大明星对象(也就是代理的对象) BigStar bigStar = new BigStar("吉哥"); // 2. 创建一个 InvocationHandler 对象,用于处理方法调用(代理对象的处理程序) InvocationHandler handler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在方法执行前添加功能 System.out.println("经纪人准备安排行程..."); // 执行方法 Object result = method.invoke(bigStar, args); // 在方法执行后添加功能 System.out.println("经纪人处理后事务..."); return result; } }; // 3. 创建代理对象 Star proxy = (Star) Proxy.newProxyInstance( Star.class.getClassLoader(), new Class[] { Star.class }, handler ); // 4. 使用代理对象调用方法 proxy.sing("只因你太美"); System.out.println("----------------------"); proxy.dance(); System.out.println("----------------------"); proxy.rap(); } }
(4)运行结果bash
复制代码
经纪人准备安排行程... 吉哥正在唱只因你太美 经纪人处理后事务... ---------------------- 经纪人准备安排行程... 吉哥正在跳舞 经纪人处理后事务... ---------------------- 经纪人准备安排行程... 吉哥正在说唱 经纪人处理后事务...
通过使用Java的动态代理机制,我们成功为大明星添加了额外的功能,而不需要修改原始的 BigStar 类。这使得我们可以轻松地在不同场景下扩展类的行为,从而更好地符合开闭原则和单一职责原则。
三、总结总的来说,动态代理就是允许在运行时创建代理对象,以代替直接访问对象。我们在示例代码中展示了如何使用动态代理来扩展类的行为,通过代理对象在原有行为上添加额外的逻辑,这也是面向切面编程(AOP)
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved