1. 什么是动态代理?
代理模式为一种设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理
动态代理的意思就是在程序运行时生成委托类的代理类来实现增强的功能。
2. 动态代理有哪些实现方式?
2.1 jdk本身自带的动态代理类。
由JVM在程序运行时生成代理类,使用java反射机制。
- demo
public class MyInvocationHandler implements InvocationHandler {
private Object target;
// 通过此方法可以生成委托类的代理类,原理通过传入的委托类的对象的类加载器生成一个代理类对象
public Object bind(Object target, Class[] interfaces) {
this.target = target;
//取得代理对象,通过被代理对象的类加载器,生成代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
interfaces, this);
}
// 通过此方法增强委托类中的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("增强内容前!");
Object invoke = method.invoke(target, args);
System.out.println("增强内容后!");
return invoke;
}
}
--------------------------------------------------------------------------------------------------------------------------------------------
public static void main(String[] args) {
MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
TestInterface test = new com.thunisoft.casespace.common.dtdl.Test();
TestInterface bind =(TestInterface) myInvocationHandler.bind(test, new Class[]{TestInterface.class});
bind.test();
bind.test2();
}
-
newProxyInstance源码分析:
···
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
// 调用处理程序(实现InvocationHandler接口的实现类)不为空
Objects.requireNonNull(h);
// 拷贝对象,设置成为常量
final Class<?>[] intfs = interfaces.clone();
// 调用java安全管理器
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}/* * Look up or generate the designated proxy class * 查找或者生成指定的代理类,该步骤会 查询 proxyClassCache 代理类缓存中是否存在该指定类型的代理类,如果不存在则生成 */ Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. * 使用指定的调用处理程序调用其构造函数。 */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } // 调用有参的构造函数生成类构造器 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } // 创建对象 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); }
}
···
2.2 ASM、cglib(基于 ASM)、Javassist 等方式
该方式后续在补充。
AccessibleObject.setAccessible方法,可以在运行时更改类属性的作用域,可以通过他绕开类的api访问控制.