动态代理(dynamic proxy)概念
利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象),代理的是接口(Interfaces),不是类(Class),也不是抽象类。在运行时才知道具体的实现,spring aop就是此原理。
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handerler)throws IllegalArgumentException
newProxyInstance,方法有三个参数:
- loader: 用哪个类加载器去加载代理对象
- interfaces:动态代理类需要实现的接口
- handler:动态代理方法在执行时,会调用handler里面的invoke方法去执行
实例
被代理对象
假设我们有一个被代理对象如下:public interface IVehical {void run();}public class Car implements IVehical { public void run() { System.out.println("Car会跑"); } }
那么我们执行如下的程序:
public class App {
public static void main(String[] args) {
IVehical car = new Car();
vehical.run();
}
}
想必大家也知道结果是打印“Car会跑”
动态代理
现在我们要对被代理对象进行扩展,又不改变其原有代码,符合开闭原则,我们使用如下方法:
实现调用处理类invocationhandler
public class VehicalInvacationHandler implements InvocationHandler {
private final IVehical vehical;
VehicalInvacationHandler(IVehical vehical){
this.vehical = vehical;
}
@override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---------before-------");
Object invoke = method.invoke(vehical, args);
System.out.println("---------after-------");
return invoke;
}
}
我们发现这个处理类由三部分构成:
- 私有的成员变量:被代理对象
- 带有参数的构造方法,传入被代理对象的实例
- 重写invoke方法:代理对象(如下面的vehical)在执行时代理方法时(如下面的run)需要动态传入:代理对象、代理的方法、执行的参数
public class App {
public static void main(String[] args) {
IVehical car = new Car();
IVehical vehical = (IVehical)Proxy.newProxyInstance(car.getClass().getClassLoader(),
Car.class.getInterfaces(),
new VehicalInvacationHandler(car));
vehical.run();
}
}
上面代码中,代理car对象,调用run方法时,自动执行invocationhandler中的invoke方法。

可以打印一下:
System.out.println(vehical.getClass());

可以看出现在的vehical实例并不是一个真正的vehical实例,而实其代理对象。我们一起来看一看Proxy.newProxyInstance是如何返回返回这个代理对象的的吧。
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
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);
}
}
