Java中什么是动态代理
动态代理可以理解为一种代理模式,它运行时就会对对象进行动态代理,将所有方法的调用都用到目标对象上。同时动态代理一般使用Java的反射机制来实现的。
Java中的动态代理需要两个关键的组件:
1.接口类:接口类定义目标对象和代理对象的共同行为。
2.代理类:代理类是动态生成的,继承Proxy类并实现了目标接口。
当调用代理对象的方法时,实际上是在调用父类的Proxy的invoke()方法,然后由invoke()方法再通过反射机制将方法调用转发到目标对象上。
使用动态代理示例代码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义接口
interface UserService {
void addUser(String name);
}
// 实现目标对象
class UserServiceImpl implements UserService {
public void addUser(String name) {
System.out.println("Add user: " + name);
}
}
// 实现InvocationHandler接口创建代理类
class UserServiceProxy implements InvocationHandler {
private Object target;
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在调用方法之前的操作
System.out.println("Before method: " + method.getName());
// 调用目标对象的方法
Object result = method.invoke(target, args);
// 在调用方法之后的操作
System.out.println("After method: " + method.getName());
return result;
}
}
public class DynamicProxyExample {
public static void main(String[] args) {
// 创建目标对象
UserService userService = new UserServiceImpl();
// 创建代理对象
UserServiceProxy proxy = new UserServiceProxy();
UserService proxyInstance = (UserService) proxy.bind(userService);
// 调用代理对象的方法
proxyInstance.addUser("Alice");
}
}
通过定义接口UserService和实现类UserServiceImpl来表示目标对象。然后使用UserServiceProxy类实现InvocationHandler接口,并通过Proxy.newProxyInstance()方法动态创建代理对象。在invoke()方法中,可以添加额外的操作,如在目标方法调用之前和之后记录日志。
输出结果如下:
Before method: addUser
Add user: Alice
After method: addUser
调用代理对象的addUser()方法时,实际执行了目标对象的addUser()方法,并且在方法调用之前和之后添加了额外的操作。
动态代理的使用场景
日志记录:通过动态代理,可以在不修改源码的情况下,在方法调用前后记录日志,实现记录日志的功能。
性能监控: 可以使用动态代理来监控方法的执行时间,统计时间,然后对代码进行优化。
事务管理: 在方法调用前开启事务,在方法调用后提交或者回滚事务,实现事务管理。
AOP(面向切面编程): 动态代理是实现AOP的一种常用方式,通过动态代理可以在不修改原始类的前提下,将额外的逻辑(如日志、事务、安全等等)横切到目标方法调用中。
安全控制: 通过动态代理,可以在方法调用进行权限检查,验证用户身份和权限,从而实现安全控制。
远程方法的调用(RPC): 动态代理可以用于实现远程方法调用,通过网络将方法调用的请求发送到远程服务器上,获取执行结果返回给客户端。
动态代理的优缺点:
优点:
1.对于代码来说,具有更低的耦合性,可以对目标对象进行扩展或者增强,避免了直接修改目标对象的代码。
2.灵活性高、通用性高,可以适用于各种不同的目标对象,不需要对目标对象编写独立的代理类
3.方便后期需求改变时对代码的修改,不需要动目标对象的代码。
缺点: 1.会有一定的性能损耗,但是又可以忽略不计,影响不大
2.需要目标对象有实现接口,没有接口就无法代理目标对象中非接口的方法。