动态代理就像是一位神奇的魔术师,它能悄无声息地在你的代码运行时,为你的对象添加各种功能,而这一切,你不需要修改任何已有的代码!
想象一下,你想要出国旅游,但你不会外语,也不熟悉当地的风俗习惯。这时候,你就可以找一家旅行社,让他们帮你安排行程、预订酒店、办理签证等等。对你来说,旅行社就相当于你的代理,你只需要告诉他们你的需求,他们就会帮你完成所有的事情。
在软件开发中,代理也是类似的概念。代理对象就像中间人一样,它会拦截对目标对象的访问,并在访问前后执行一些额外的操作,比如记录日志、权限校验、缓存等等。
代理模式有很多种实现方式,而动态代理则是其中最灵活的一种。它最大的特点就是在程序运行时,动态地创建代理对象和代理类,而不需要我们手动编写代理类的代码。
那么,Java是如何实现动态代理的呢?答案就是——反射!(点击查看什么是反射)
Java提供了以下三种方式来实现动态代理:
本文将重点介绍使用最广泛的JDK动态代理,其他两种方式留待后续文章中探讨。
假设我们有一个 UserService 接口和一个 UserServiceImpl 实现类,现在我们想在调用 UserServiceImpl 的每个方法前后都打印一条日志,记录方法的执行时间。
1. 定义接口和实现类:
// UserService 接口
public interface UserService {
void createUser(String username, String password);
void deleteUser(String username);
}
// UserServiceImpl 实现类
public class UserServiceImpl implements UserService {
@Override
public void createUser(String username, String password) {
System.out.println("创建用户:" + username);
// 模拟业务逻辑执行
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void deleteUser(String username) {
System.out.println("删除用户:" + username);
// 模拟业务逻辑执行
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}2. 创建 InvocationHandler 实现类:
// InvocationHandler 实现类,用于处理代理逻辑
public class LogInvocationHandler implements InvocationHandler {
// 目标对象
private Object target;
public LogInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 方法执行前的逻辑
long startTime = System.currentTimeMillis();
System.out.println("开始执行方法:" + method.getName());
// 调用目标对象的方法
Object result = method.invoke(target, args);
// 方法执行后的逻辑
long endTime = System.currentTimeMillis();
System.out.println("方法执行结束:" + method.getName() + ",耗时:" + (endTime - startTime) + "ms");
return result;
}
}3. 创建代理对象:
public class Main {
public static void main(String[] args) {
// 创建目标对象
UserService userService = new UserServiceImpl();
// 创建 InvocationHandler 对象
LogInvocationHandler handler = new LogInvocationHandler(userService);
// 创建代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(), // 类加载器
userService.getClass().getInterfaces(), // 接口数组
handler); // InvocationHandler 对象
// 调用代理对象的方法
proxy.createUser("zhangsan", "123456");
proxy.deleteUser("lisi");
}
}代码解释:
运行结果:
开始执行方法:createUser
创建用户:zhangsan
方法执行结束:createUser,耗时:104ms
开始执行方法:deleteUser
删除用户:lisi
方法执行结束:deleteUser,耗时:103ms4.invoke() 方法
在Java中,invoke方法主要用于反射机制,它属于java.lang.reflect.Method类。通过这个方法,可以动态地调用某个类的实例方法或静态方法。
invoke方法的基本用法
public Object invoke(Object obj, Object... args) throws IllegalAccessException, InvocationTargetException;obj:调用方法的对象实例。如果是静态方法,可以传null。args:调用方法时需要的参数,可以是可变参数数组。使用示例
下面是一个简单的例子,演示如何使用invoke方法:
import java.lang.reflect.Method;
class Example {
public void sayHello(String name) {
System.out.println("Hello, " + name + "!");
}
}
public class Main {
public static void main(String[] args) {
try {
// 创建 Example 类的实例
Example example = new Example();
// 获取 sayHello 方法
Method method = Example.class.getMethod("sayHello", String.class);
// 调用 sayHello 方法
method.invoke(example, "World");
} catch (Exception e) {
e.printStackTrace();
}
}
}注意事项
invoke方法可能会抛出多个异常,如IllegalAccessException和InvocationTargetException,需要适当处理。动态代理是Java中一个非常强大的机制,它可以帮助我们实现很多灵活的功能,比如:
希望通过本文的介绍,你已经对Java动态代理有了初步的了解。在实际开发中,我们可以根据具体的需求,灵活运用动态代理,让我们的代码更加优雅高效!感谢各位看官的观看,下期见,谢谢~