• 使用代理对象执行实现类目标方法异常


    使用JDK方式创建动态代理对象时,通常都是会强转为目标接口类型。

    public class Test {
    
        public static void main(String[] args) throws Exception{
    
            BaseController baseController = new BaseControllerImpl();
            InvocationHandler handler = new MyInvocationHandler(baseController);
            BaseController target = (BaseController) Proxy.newProxyInstance(BaseController.class.getClassLoader(), new Class[]{BaseController.class}, handler);
            target.a4("111");
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    此时的target就是一个代理对象,同时是Proxy与BaseController的实例,此时以接口的形式来调用方法调用的时接口的方法是可以的,什么意思? 可参考如下代码

        public static void main(String[] args)throws Exception {
            Method a4 = BaseController.class.getMethod("a4", String.class);
    
            Method a4Impl = BaseControllerImpl.class.getMethod("a4", String.class);
    
            BaseControllerImpl baseController = new BaseControllerImpl();
    
            a4Impl.invoke(baseController,"111");
            a4.invoke(baseController,"222");
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    BaseController是接口,BaseControllerImpl 是实现类,获取了接口的a4方法和实现类型的a4方法,然后创建了BaseController的一个实现类,用实现类去分别反射调用这两个method,发现调用成功了。

    在这里插入图片描述

    但是如果是使用创建的代理对象去执行实现类的方法则会抛出异常。

        public static void main(String[] args) throws Exception{
    
            BaseController baseController = new BaseControllerImpl();
            InvocationHandler handler = new MyInvocationHandler(baseController);
            BaseController target = (BaseController) Proxy.newProxyInstance(BaseController.class.getClassLoader(), new Class[]{BaseController.class}, handler);
            Method a4 = BaseController.class.getMethod("a4", String.class);
            Method a4Impl = BaseControllerImpl.class.getMethod("a4", String.class);
            a4.invoke(target,"111");
            a4Impl.invoke(target,"222");
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    这个其实也可以很好想明白target是一个代理对象,是BaseController的代理对象,本身和BaseControllerImpl是没有关系的,他俩都实现了BaseController接口,因此可以说是兄弟关系,但是兄弟之间就不能实现相同方法的调用了,必须得是父类或自身得方法可以。所以在JDK实现的代理中,在调用接口目标方法时,是调用的接口的方法。

    可通过debug查看在代理对象调用方法时的method签名,可以很明显看到是接口中的方法签名。对于Spring中声明的切面来说,切面类并不能生成代理对象,只不过是通知Spring根据切面配置的pointcut来检测bean是否需要创建代理对象,用哪种方式创建等,而切面类声明的方法只是用来告诉Spring是哪种通知类型。

    在这里插入图片描述

  • 相关阅读:
    家用厨房电器测试报告办理流程
    【大数据】Apache NiFi 助力数据处理及分发
    CSDN Markdown编辑技巧 -使用Katex插入数学公式
    CPT205-Computer Graphics
    Maven发布自己项目到maven中央仓库
    京东云联合Forrester咨询发布混合云报告 云原生成为驱动产业发展新引擎
    【GO】LGTM_Grafana_Tempo(2)_官方用例改后实操
    Flutter 3.3 现已发布
    【Linux私房菜】第三期——实用指令
    140.【鸿蒙OS开发-01】
  • 原文地址:https://blog.csdn.net/qq_43750656/article/details/126139768