且玩一玩动态代理之小栗子

2023-05-16

直接上代码

文章目录

  • 前提
  • 代码
      • newProxyInstance
      • InvocationHandler

前提

这里需要结合另一篇博文来理解:

代码

接口:

package com.xmonster.demo2;

public interface IService {

    public void sayHello();

}

真实实现类:

package com.xmonster.demo2;

public class RealService implements IService{
    @Override
    public void sayHello() {
        System.out.println("hello i am xmonster!");
    }
}

工具+测试:

package com.xmonster.demo2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class SimpleInvocationHandler implements InvocationHandler {

    private Object realObj;
    public SimpleInvocationHandler(Object realObj) {
        this.realObj = realObj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("entering"+method.getName());
        Object invokeResult = method.invoke(realObj, args);
        System.out.println("leaving"+method.getName());
        return invokeResult;

    }

    public static void main(String[] args) {
        IService realService = new RealService();
        IService proxy =(IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class<?>[]{IService.class},
                new SimpleInvocationHandler(realService));
        proxy.sayHello();

    }
}

测试结果:
在这里插入图片描述

newProxyInstance

来看看newProxyInstance的三个参数

private static Object newProxyInstance(ClassLoader loader, // null if no SecurityManager
                                       Constructor<?>[] interfaces,
                                       InvocationHandler h)

参数:

  1. ClassLoader loader表示类加载器,在这里使用和接口一样的类加载器
  2. interfaces表示代理类要实现的接口列表,是一个数组,元素的类型只能是接口,不能是普通类
  3. InvocationHandler 它是一个接口,只定义了一个invoke方法,对代理接口所有方法的调用都会转给这个方法来处理

newProxyInstance的返回值是Object,可以被强转为interfaces数组当中的某个接口类型,在这里直接强转为了IService类型,注意:它不能够被强转为某个类,比如RealService !

InvocationHandler

package java.lang.reflect;

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

参数:

  1. proxy表示代理本身,注意,他不是被代理的对象
  2. method表示正在被调用的方法
  3. args表示方法的参数
Object invokeResult = method.invoke(realObj, args);

这里调用的是method的invoke方法,传递的是实际的对象realObj,不能将proxy作为参数传递给method.invoke,会出现死循环,因为它本身就有这个方法
以下是method的invoke方法源码

 @HotSpotIntrinsicCandidate
    public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {
        if (!override) {
            Class<?> caller = Reflection.getCallerClass();
            checkAccess(caller, clazz,
                        Modifier.isStatic(modifiers) ? null : obj.getClass(),
                        modifiers);
        }
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }
        return ma.invoke(obj, args);
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

且玩一玩动态代理之小栗子 的相关文章

随机推荐