码迷,mamicode.com
首页 > 其他好文 > 详细

jdk 中的代理

时间:2019-11-18 20:23:38      阅读:79      评论:0      收藏:0      [点我收藏+]

标签:tcl   imp   如何使用   功能   name   factory   结果   efi   teacher   

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 中的代理

标签:tcl   imp   如何使用   功能   name   factory   结果   efi   teacher   

原文地址:https://www.cnblogs.com/futureT/p/11884453.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!