java.lang.reflect.Proxy
代理:语义就是,让某个事物代表另外一个事物。
实现的功能:让不方便出现的事物,有另外的事物进行处理。
对于Java来说,我个人的理解就是:需要类A来代表类B,类B的方法在类A中有实现,且类A不继承自类B。
为了理解,如下类A均是代理类B
那么Java中的源码是如何实现的呢?
-------note:查看源码和设计是个相反的过程,需要通过如何使用来看这个源码的实现。
获得代理类的方法由如下该类实现。
java.lang.reflect.Proxy.newProxyInstance(ClassLoader classLoader, Class<?>[] interfaces, InvocationHandler h);
Parameters:
loader
- the class loader to define the proxy class
interfaces
- the list of interfaces for the proxy class to implement
h
- the invocation handler to dispatch method invocations to
源码部分查看 该方法返回结果。
return cons.newInstance(new Object[]{h});
源码部分 摘出 关于cons 的内容如下:
final Constructor<?> cons = cl.getConstructor(constructorParams);----------->method:newProxyInstance paramArgs:constructorParams
constructorParams---------->field:
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
Class<?> cl = getProxyClass0(loader, intfs);---------->method:newProxyInstance
getProxyClass0(loader, intfs); -------->method: getProxyClass0 return:proxyClassCache.get(loader, interfaces); returnType:Class
proxyClassCache---->field:
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
这样就很清晰了。获取了InvocationHandler 匿名类的构造函数对象,通过类B的classLoader和intfs 来获取Class 实例c1,
对于InvocationHandler--h ,h代表要继承的接口,
该接口的方法是:invoke(Object proxy,Method method,Object[] args)
如下是关于 使用的示例。
package main.test1; public interface Work { public void work(); }
package main.test1; public class Teacher implements Work,Teach { @Override public void work() { System.out.println("teacher work"); } @Override public void teach() { // TODO Auto-generated method stub System.out.println("teaching"); } }
package main.test1; public interface Teach { public void teach(); }
package main.test1; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler{ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return method.invoke(new Teacher(), args); } }
package main.test1; import java.lang.reflect.Proxy; public class Test1 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub MyInvocationHandler myInvocationHandler = new MyInvocationHandler(); Work proWork=(Work) Proxy.newProxyInstance(Class.forName("main.test1.Teacher").getClassLoader(), Class.forName("main.test1.Teacher").getInterfaces(), myInvocationHandler); proWork.work(); Teach pTeach = (Teach) Proxy.newProxyInstance(Class.forName("main.test1.Teacher").getClassLoader(), Class.forName("main.test1.Teacher").getInterfaces(), myInvocationHandler); pTeach.teach(); } }
结果:
teacher work
teaching
思考:如果直接创建:
Work work = new Teacher();
Teach teach = new Teacher();
work.work();
teach.teach();
得到的结果是一样的,而且在InvocationHandler 中也是需要method.invoke(proxyClass,args)。
想法:
通过直接创建的匿名类,是一种静态的创建匿名类的过程。如果只能知道接口,而没有该类的话,我们需要通过其他地方获取该类的ClassLoader的时候,Proxy显然会更有优势。另外思考关于spring 容器中的AOP,如何关联AOp中的关键地方。
Java中运用到动态代理的地方非常多。该设计模式应该如何工厂模式一样详加运用。