什么是动态代理
可以在不修改原有类代码的情况下,对类功能接口进行拦截和增强,而且对于用户来说是透明的,好像没有发生任何变化。
比如说在 Spring 中我们给 UserService 的某个方法增加了 @Transactional 事务注解后,Spring 在进行 Bean 加载的时候,它检测到了这个注解,就会创建一个代理类来替换掉 UserService 对象,然后在调用对应的事务方法中,他就可以通过代理类去先开启事务,进行一系列操作,最后再提交或者回滚事务。
试想一下如果不通过动态代理我们是不是就要写很多代码,而且不易维护增加工作量。
如果一个类里面没有特殊的注解,Spring 加载的就是通过构造器创建的普通对象。
我们在使用上是没有察觉的什么差别的,在其它地方上我们还是通过 @Autowired 注入 UserService 然后调用 userService.xxx 方法
如果我们使用静态代理的话,我们就需要为每个类都写一遍代码
public class Test2 {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService userServiceProxy = new UserServiceProxy(userService);
userServiceProxy.add();
}
}
class UserServiceProxy implements UserService {
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
@Override
public void add() {
System.out.println("add before");
userService.add();
System.out.println("add after");
}
}
class ProjectServiceProxy implements ProjectService {
private ProjectService projectService;
public ProjectServiceProxy(ProjectService projectService) {
this.projectService = projectService;
}
@Override
public void add() {
System.out.println("add before");
projectService.add();
System.out.println("add after");
}
}
Java 动态代理
Java 动态代理,要求被代理的类必须实现一个接口,他会在运行时候动态生成代理类来替换掉原始的类
interface UserService {
void add();
}
class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("add user");
}
}
class TestInvocationHandler implements InvocationHandler {
private Object object;
public TestInvocationHandler(Object object) {
this.object = object;
}
public Object getProxy() {
return Proxy
.newProxyInstance(Thread.currentThread()
.getContextClassLoader(),
object.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("添加之前");
Object obj = method.invoke(object, args);
System.out.println("添加之后");
return obj;
}
}
public class Test {
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
UserService userService = new UserServiceImpl();
TestInvocationHandler invocationHandler = new TestInvocationHandler(userService);
UserService userServiceProxy = (UserService) invocationHandler.getProxy();
userServiceProxy.add();
}
}
首先调用 Proxy.newProxyInstance()
在其中会调用
getProxyClass0(loader, intfs)
来创建代理类
然后从
proxyClassCache
中查找是否已经生成过了该代理类,生成了就直接返回
否则执行加载过程最终会调用
generateProxyClass()
来生成代理类字节码文件,然后调用 defineClass0()
将字节码文件解析为 class 并且加载到内存中
我们将生成的字节码文件下载到本地,通过
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
这个配置即可
public final class $Proxy0 extends Proxy implements UserService {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void add() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("array.UserService").getMethod("add");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
最后在 newProxyInstance()
方法最后会调用通过构造器反射创建对象
在创建的时候就将我们自己实现的 InvocationHandler 设置进去了
当我们调用 userService.add()
的时候,实际上调用的是代理类的 add()
方法,然后调用我们自定义的 TestInvocationHandler 的 invoke 方法
用途
- 各种框架中比如 AOP,过滤器,拦截器
- 日志拦截、事务拦截、权限拦截
- 类功能的增强与解耦