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中运用到动态代理的地方非常多。该设计模式应该如何工厂模式一样详加运用。