Spring AOP入门时原始接口丢失

4
这是我的Spring AOP配置。
<bean id="myObject" class="com.madzone.learn.spring.aop.OriginalClass"></bean>
<bean id="aspect" class="com.madzone.learn.spring.aop.AspectClass"></bean>
<aop:config>
    <aop:aspect ref="aspect">
        <aop:declare-parents
            types-matching="com.madzone.learn.spring.aop.OriginalClass+"
            implement-interface="com.madzone.learn.spring.aop.IntroducedInterface"
            default-impl="com.madzone.learn.spring.aop.IntroducedInterfaceImpl" />
    </aop:aspect>

ApplicationContext context = new ClassPathXmlApplicationContext("myApp.xml");
Object myObject = context.getBean("myObject");
if (myObject instanceof OriginalClass) {
    System.out.println("This is OriginalClass");
}
if(myObject instanceof IntroducedInterface) {
    System.out.println("This is IntroducedInterface");
}

通过这个介绍,我可以调用IntroducedInterface中的方法。但是,我无法访问OriginalClass的方法。在上面的代码片段中,我从未打印出“这是OriginalClass”。
根据“Introduction”的定义,我理解实现新接口的代理将扩展自OriginalClass,并使其方法也可访问。
我错过了什么吗?如果有的话,有人能解释一下原因吗?
PS: 以下是Spring in Action(第3版)中描述此内容的图片。 Can the caller access both the interfaces 'Existing method' and 'Introduced method'?
1个回答

6

从“介绍”的定义中,我了解到实现新接口的代理将从OriginalClass扩展,并使其方法也可访问。

我不确定您是从哪里得到这个印象的。默认情况下,Spring AOP是建立在JDK动态代理上的,它只适用于接口。无法代理具体类。Spring确实支持使用CGLIB代理来代理类,但是参考指南不鼓励使用,而是倡导通过编程接口来减少耦合。


我正在阅读《Spring实战》,其中有一张图片描述了这个程序(第3版中的图4.7)。在进一步阅读细节之前,我错误地编写了该程序,并期望它能够成功运行。 - Madhusuthanan Seetharam
进一步阅读注释方面,我发现以下内容:“当它发现一个使用@Aspect注释的bean时,它将自动创建一个代理,该代理将调用委托给代理的bean或介绍实现,具体取决于被调用的方法是属于代理的bean还是介绍的接口。” 我还有什么遗漏的吗?除此之外,我的测试(在注释版本中)证实只有介绍的接口是可访问的,而原始的代理bean则不可访问。 - Madhusuthanan Seetharam
2
您添加的图表是准确的。在使用AOP时,所有调用都会转到代理实例,代理实例决定如何处理它们。JDK动态代理的代理实例只能实现接口,而不能扩展类。因此,代理无法具有您尝试调用的方法,因为它们在类上。只需向代理类添加一个接口即可解决此问题。代理系统将看到该接口并将其添加到代理实现的接口中。 - Ryan Stewart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接