zl程序教程

您现在的位置是:首页 >  后端

当前栏目

InvocationHandle的invoke方法[通俗易懂]

方法 通俗易懂 Invoke
2023-06-13 09:11:53 时间

大家好,又见面了,我是你们的朋友全栈君。

在学习代理模式中接触到了动态代理的相关内容,这是AOP的核心内容。先用一个例子说明 动态代理 的使用

//接口(动态代理只能代理接口)  
public interface Subject {  
      
    public void request();  
}  
//接口实现 :实现了Subject的request()方法  
public class RealSubject implements Subject{  
      
    public void request(){  
        System.out.println("From real subject.");  
    }  
} 

Inb

//实现了InvocationHandler  接口
public class DynamicSubject implements InvocationHandler  
{  
    private Object obj;//这是动态代理的好处,被封装的对象是Object类型,接受任意类型的对象  
  
    public DynamicSubject()  
    {  
    }  
  
    public DynamicSubject(Object obj)  
    {  
        this.obj = obj;  
    }  
  
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  
    {  
        System.out.println("before calling " + method);  
  
        method.invoke(obj, args);  
  
        System.out.println("after calling " + method);  
  
        return null;  
    }  
  
}  
public class Client {  
  
    public static void main(String[] args) throws Throwable{  
        // TODO Auto-generated method stub  
  
        Subject rs=new RealSubject();//这里指定被代理类  
        InvocationHandler ds=new DynamicSubject(rs);  
        Class<?> cls=rs.getClass();  
          
        //生成代理类  ,注意subject是Proxy的子类并且实现了Subject接口的一个类。
          
        Subject subject=(Subject) Proxy.newProxyInstance(  
                cls.getClassLoader(),cls.getInterfaces(), ds);       
}



以上就是动态代理的使用方法,有一点很奇怪,那就是invoke方法是如何被调用的呢? 可以看到在以上代码中并没有invoke的身影,那是因为有关invoke的调用时在Proxy类中,invoke方法并不是给我们显示的调用,查看源码我们可以看到。  
首先看Proxy的静态方法newProxyInstance()
public static Object newProxyInstance(ClassLoader loader,  

        Class<?>[] interfaces,  
        InvocationHandler h)  
throws IllegalArgumentException  
{  
    if (h == null) {  
        throw new NullPointerException();  
    }  
  
    /* 
     * Look up or generate the designated proxy class. 
     */  
    Class cl = getProxyClass(loader, interfaces);  
  
    /* 
     * Invoke its constructor with the designated invocation handler. 
     */  
    try {  
           /* 
            * Proxy源码开始有这样的定义: 
            * private final static Class[] constructorParams = { InvocationHandler.class }; 
            * cons即是形参为InvocationHandler类型的构造方法 
           */  
        Constructor cons = cl.getConstructor(constructorParams);  
        return (Object) cons.newInstance(new Object[] { h });    //此处返回.
    } catch (NoSuchMethodException e) {  
        throw new InternalError(e.toString());  
    } catch (IllegalAccessException e) {  
        throw new InternalError(e.toString());  
    } catch (InstantiationException e) {  
        throw new InternalError(e.toString());  
    } catch (InvocationTargetException e) {  
        throw new InternalError(e.toString());  
    }  
}  

这个方法实际是利用反射,返回了一个Proxy的子类,实现了指定的接口,返回的类叫做$Proxy0, 这个类包含了invoke的秘密! 请看源码:

public final class $Proxy0 extends Proxy implements Subject {  
    private static Method m1;  
    private static Method m0;  
    private static Method m3;  
    private static Method m2;  
  
    static {  
        try {  
            m1 = Class.forName("java.lang.Object").getMethod("equals",  
                    new Class[] { Class.forName("java.lang.Object") });  
  
            m0 = Class.forName("java.lang.Object").getMethod("hashCode",  
                    new Class[0]);  
  
            m3 = Class.forName("***.RealSubject").getMethod("request",  
                    new Class[0]);  
  
            m2 = Class.forName("java.lang.Object").getMethod("toString",  
                    new Class[0]);  
  
        } catch (NoSuchMethodException nosuchmethodexception) {  
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
        } catch (ClassNotFoundException classnotfoundexception) {  
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
        }  
    } //static  
  
    public $Proxy0(InvocationHandler invocationhandler) {  
        super(invocationhandler);  
    }  
  
    @Override  
    public final boolean equals(Object obj) {  
        try {  
            return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final int hashCode() {  
        try {  
            return ((Integer) super.h.invoke(this, m0, null)).intValue();  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    public final void request() {  
        try {  
            super.h.invoke(this, m3, null);  
            return;  
        } catch (Error e) {  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final String toString() {  
        try {  
            return (String) super.h.invoke(this, m2, null);  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
}

该类中利用反射获取到了4个方法,Object类自带的equals,hasCode,toString ,以及接口Subject的唯一方法request,因此当我们在主函数中调用request.xxx(方法名),就是在$Proxy0类中调用相应方法,每个方法中都有 super.h.invoke(this,m3,null); invoke函数在此起到了作用!

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/138722.html原文链接:https://javaforall.cn