借鉴:
https://blog.csdn.net/yangaiyu/article/details/73827043
若自己实现代码增强,则需要为每个目标对象单独编写一个代理Class对象然后用类加载器加载,实例化,再调用,这样每个目标对象都得单独地编写代理Class对象以达到目的(即静态代理)。
为了减少代理类地编写,我们类的消息一般都由Class对象在JVM方法区中被加载(反射和new都是),若想不编写代理class还要有目标类的信息,自然而然地可以想到接口,若能对接口进行动态代理,则可将实现该接口并调用该接口中的方法(可能不止实现一个接口)的目标类归为以类进行代码编写(这就是为什么要使用动态代理的原因),但是,接口并不能实例化
但java.lang.reflect.Proxy类有个getProxyLoader(ClassLoader,interfaces)方法,只要你给他传入类加载器和一组接口,它就能给你返回代理Class对象。(意味着它变成了一个对象,可以带有构造器进行实例化)
InvocationHandler handler = new DynamicProxy(realSubject);
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy: 指代我们所代理的那个真实对象
method: 指代的是我们所要调用真实对象的某个方法的Method对象
args: 指代的是调用真实对象某个方法时接受的参数
可能会以为返回的这个代理对象会是Calculator类型的对象,或者是InvocationHandler的对象,结果却不是,首先我们解释一下为什么我们这里可以将其转化为Subject类型的对象?原因就是在getPorxyClass这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么我这个代理对象就会实现了这组接口,这个时候我们当然可以将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Subject类型,所以就可以将其转化为Subject类型了。
同时我们一定要记住,以上获取代理Class、得到有参构造函数、实例化后创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。
* public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
原文:https://www.cnblogs.com/eternal-heathens/p/13341895.html