动态代理是在程序运行时生成代理对象,而不是在编译时确定。在 Java 中,动态代理通常使用 Java 反射机制实现。Java 提供了 java.lang.reflect
包,其中的 Proxy
类和 InvocationHandler
接口是实现动态代理的关键。
动态代理的核心思想是,通过一个代理类,实现 InvocationHandler
接口,动态生成代理对象。代理对象在运行时负责处理被代理对象的方法调用,并可以在方法调用前后执行额外的逻辑。
我的个人理解:动态代理的作用其实就是为了在不删改原有的代码基础上,为对象添加新的行为或功能
现在公司有个增删改查,需要让你在增删改查每个方法添加一个日志
但是不能改变原有代码,因为有时候改变原有代码会出现一些莫名其妙的bug
这就是开闭原则,是面向对象设计中的一个基本原则
public interface UserService {
public void add();
public void update();
public void delete();
public void query();
}
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("add");
}
@Override
public void update() {
System.out.println("update");
}
@Override
public void delete() {
System.out.println("delete");
}
@Override
public void query() {
System.out.println("query");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class UserServiceProxy implements InvocationHandler {
//这是为了代理任何对象 被代理对象
Object target;
//当传入什么实现类,就会代理哪个实现类 方法名随便
public void setUserService(Object target) {
this.target = target;
}
public Object getProxy()
{
return Proxy.newProxyInstance(
target.getClass().getClassLoader(), target.getClass().getInterfaces()
,this);
}
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
log(method.getName());
method.invoke(target,args);
return null;
}
public void log(String msg)
{
System.out.println(msg);
}
}
public Object getProxy()
{
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
方法的第一个参数用于获取被代理对象的所有属性:
传入被代理对象的类加载器
类加载器确保新生成的代理对象能够访问目标对象的类
传入被代理对象所实现的接口
获取目标对象所实现的接口。这是为了确保代理对象实现了与目标对象相同的接口,从而可以代理相同的方法
this
关键字表示当前对象,即 UserServiceProxy
对象。传入this 这个是死的
UserServiceProxy
实现了 InvocationHandler
接口,所以它可以作为代理对象的 InvocationHandler
。
为了处理invoke的第一个参数object 也就是这是谁的代理对象。
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
log(method.getName());
method.invoke(target,args);
return null;
}
不用填 因为getProxy已经做了
代理对象,即通过 Proxy.newProxyInstance
方法生成的代理对象。在 invoke
方法中,你可以使用这个对象来调用被代理对象的方法。
传入被代理对象
被代理对象的方法。通过这个参数,你可以获取方法的名称、参数、返回类型等信息。
方法的参数数组。这是被代理方法调用时传递的参数。
这一行使用 method.invoke
调用了被代理对象(target
)的方法。通过传递 args
数组作为参数,实际执行了被代理方法。这是在执行被代理方法的地方。
public class Client {
public static void main(String[] args) {
UserServiceProxy userServiceProxy = new UserServiceProxy();
UserServiceImpl userService = new UserServiceImpl();
• userServiceProxy.setUserService(userService);
• UserService proxy = (UserService) userServiceProxy.getProxy();
• proxy.add();
• }
}