📅  最后修改于: 2023-12-03 15:31:33.372000             🧑  作者: Mango
在Java开发中,我们经常需要从一个对象向另一个对象转发请求。但是,有时候这个目标对象并不存在,或者我们不知道目标对象的信息。在这种情况下,我们可以使用Java的动态代理机制来实现在不存在的末尾添加转发。
动态代理是Java中常用的一种代理机制。它可以创建一个代理对象,该代理对象与原对象实现相同的接口,并且可以拦截方法的调用。我们可以在拦截方法的前后进行一些操作,比如打印日志、修改参数、验证权限等。
动态代理有两种方式:基于接口的代理和基于类的代理。基于接口的代理需要目标对象实现一个接口,代理对象则实现与目标对象相同的接口;而基于类的代理则是创建一个目标对象的子类,并且代理对象继承自这个子类。
我们来看一个基于接口的动态代理的示例。假设我们有一个接口UserService
,其中包含一个getUserById
方法,我们想要在调用这个方法时进行一些操作,比如打印日志。我们可以通过如下代码实现:
public interface UserService {
void getUserById(int id);
}
public class UserServiceImpl implements UserService {
@Override
public void getUserById(int id) {
System.out.println("Get user by id: " + id);
}
}
public class UserServiceProxy implements InvocationHandler {
private Object target;
public UserServiceProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After " + method.getName());
return result;
}
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new UserServiceProxy(userService));
proxy.getUserById(1001);
}
}
上述代码中,UserServiceImpl
实现了UserService
接口,并且实现了getUserById
方法。UserServiceProxy
是一个代理对象,它实现了InvocationHandler
接口,并且包含一个目标对象target
,用于指向实际的实现类。
在invok
方法中,我们打印出了目标方法的名称,然后调用了目标方法,最后再打印出目标方法的名称。通过这种方式,我们就可以在目标方法的前后进行一些操作。
在main
方法中,我们创建了一个真正的实现类userService
和一个代理类proxy
,代理类和实现类都实现了UserService
接口。我们使用Proxy.newProxyInstance
方法创建了一个代理对象,并且把目标对象传递给了代理对象的构造方法中。然后,我们调用了代理对象的getUserById
方法,代理对象会自动调用invok
方法,并且在其中实现了前置和后置处理。
通过动态代理机制,我们可以很方便地实现在不存在的末尾添加转发。这种方式在Spring等框架中也得到广泛使用,通过AOP(面向切面编程)的方式,在方法调用前后加上一些通用的处理逻辑,比如日志、事务等。