java动态代理

静态代理是通过实现类去继承接口并实现接口方法来实现;而动态代理并没有这个实现类,动态代理在运行时通过Proxy.newProxyInstance()去动态创建接口对象,然后去调用接口方法。

通过Proxy.newProxyInstance()创建接口实例,该方法的主要源码如下(有删减),其实就是通过接口类和类加载器获得代理类,通过反射得到代理类的构造函数,进而创建一个对象出来。

    /**

     * @param   loader the class loader to define the proxy class
     * @param   interfaces the list of interfaces for the proxy class
     *          to implement
     * @param   h the invocation handler to dispatch method invocations to

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
    {
        final Class<?>[] intfs = interfaces.clone();     
        Class<?> cl = getProxyClass0(loader, intfs);
            try {            
              final Constructor<?> cons = cl.getConstructor(constructorParams);
              final InvocationHandler ih = h;
              if (!Modifier.isPublic(cl.getModifiers())) {              

                cons.setAccessible(true);
              }
              return cons.newInstance(new Object[]{h});
        }  catch (Exception e) {}
    }

有三个参数

1、ClassLoader loader,可以使用接口类的ClassLoader。

2、Class<?>[] interfaces,需要实现的接口数组,至少要写一个接口类class进去

3、InvocationHandler h,用来处理接口方法调用的InvocationHandler实例。

InvocationHandler实例通过new InvocationHandler()来创建,主要源码如下:


public interface InvocationHandler {

     * @param   proxy the proxy instance that the method was invoked on
     *
     * @param   method the {@code Method} instance corresponding to
     * the interface method invoked on the proxy instance.  The declaring
     * class of the {@code Method} object will be the interface that
     * the method was declared in, which may be a superinterface of the
     * proxy interface that the proxy class inherits the method through.
     *
     * @param   args an array of objects containing the values of the
     * arguments passed in the method invocation on the proxy instance,
     * or {@code null} if interface method takes no arguments.
     * Arguments of primitive types are wrapped in instances of the
     * appropriate primitive wrapper class, such as
     * {@code java.lang.Integer} or {@code java.lang.Boolean}.
     *
     * @return  the value to return from the method invocation on the
     * proxy instance.  If the declared return type of the interface
     * method is a primitive type, then the value returned by
     * this method must be an instance of the corresponding primitive
     * wrapper class; otherwise, it must be a type assignable to the
     * declared return type.  If the value returned by this method is
     * {@code null} and the interface method's return type is
     * primitive, then a {@code NullPointerException} will be
     * thrown by the method invocation on the proxy instance.  If the
     * value returned by this method is otherwise not compatible with
     * the interface method's declared return type as described above,
     * a {@code ClassCastException} will be thrown by the method
     * invocation on the proxy instance.

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}
invoke(Object proxy, Method method, Object[] args)第一个参数表示之前Proxy.newProxyInstance()创建的接口实例,第二个参数表示调用的接口方法,最后一个参数表示接口方法的参数。在invoke中处理方法逻辑,这也是面向切面编程的地方。

创建接口实例和InvocationHandler实例后,将Object类型的接口实例强制转为接口类型,然后调用接口方法,然后在InvocationHandler实例的invoke方法中处理自己的业务逻辑即可。

demo如下:

    public void TestProxy(View view) {
        InvocationHandler invocationHandler=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Log.d(TAG, "invoke: method="+method);
                if (method.getName().equals("study")) {
                    Log.d(TAG, "invoke: "+args[0]+" is study");
                }
                return null;
            }
        };
        IPersion developer = (IPersion) Proxy.newProxyInstance(IPersion.class.getClassLoader(),new Class[]{IPersion.class},invocationHandler);
        developer.study("developer");
    }

点击view后log打印如下:

2020-01-27 21:11:52.922 21127-21127/com.example.myapplication D/MainActivityLog: invoke: method=public abstract void com.example.myapplication.IPersion.study(java.lang.String)
2020-01-27 21:11:52.922 21127-21127/com.example.myapplication D/MainActivityLog: invoke: developer is study

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值