jdk 中的代理

Posted futuret

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk 中的代理相关的知识,希望对你有一定的参考价值。

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

以上是关于jdk 中的代理的主要内容,如果未能解决你的问题,请参考以下文章

(java反射-JDK动态代理)+CGLIB动态代理

深入浅出JDK动态代理

JDK动态代理与CGLib动态代理

动态代理

Spring Boot 中的 AOP,到底是 JDK 动态代理还是 Cglib 动态代理?

JDK和Cglib动态代理