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

01-10 12:55