Spring(Java):在非线性类层次结构中不会触发方面

Spring(Java):在非线性类层次结构中不会触发方面,java,spring,aop,aspect,class-hierarchy,Java,Spring,Aop,Aspect,Class Hierarchy,当类层次结构不是线性的时,在基接口上定义时不会触发方面 最有趣的是:当向实现的父类添加委托实现(参见最后一个代码块)时,测试变为绿色(方面按预期触发) 问题:为什么它不能像示例中描述的那样工作,为什么它可以与授权实现一起工作? 示例(抱歉,未找到较短的示例): 测试: 方面: @Aspect @Component public static class MyAspect { @Before("execution(* *..SpecializedInterface+.doSomethin

当类层次结构不是线性的时,在基接口上定义时不会触发方面

最有趣的是:当向实现的父类添加委托实现(参见最后一个代码块)时,测试变为绿色(方面按预期触发)

问题:为什么它不能像示例中描述的那样工作,为什么它可以与授权实现一起工作?

示例(抱歉,未找到较短的示例):

测试:

方面:

@Aspect
@Component
public static class MyAspect {

    @Before("execution(* *..SpecializedInterface+.doSomething())")
    public void applyAspect() {
        aspectCalled = true;
    }
}
接口:

public static interface TheInterface {
    void doSomething();
}

public static interface SpecializedInterface extends TheInterface {
    // inherits doSomething
    // defines some other methods
}
抽象实现(模板模式):

实现bean:

@Component
public static class TemplateImplementation extends SpecializedTemplate {
    @Override
    void doOneStep() {
        implementationCalled = true;
    }
}
(如果您感兴趣:测试设置:)

难看的解决方法:将此代码段添加到SpecializedTemplate

    @Override
    public void doSomething() {
        super.doSomething();
    }
那么,为什么需要这种变通方法呢?

Thomas Stets已经解释了字节码和JVM的内容,所以我将为您的问题提供一个解决方案,另请参阅我对一个非常类似问题的解答

@方面
公共静态类MyAspect{
@在(“执行(**…接口+.doSomething())&目标(专用接口)”之前
public void applyAspect(专用接口专用接口){
aspectCalled=true;
}
}

也就是说,切入点以实际定义方法的基本接口为目标,然后将目标限制在您选择的专用子接口上。这将使您的测试变为绿色。

我对细节不太确定,但我猜:@Before(“execution(**…SpecializedInterface+.doSomething()))告诉它在实现SpecializedInterface的任何类中将方面应用于doSomething()。SpecializedTemplate不包含doSomething()(字节码),因此不应用方面。一旦添加了变通方法,类就包含了方法,并且可以应用方面?它是否包含字节码中的doSomething()方法?java编译器是否将抽象类中的所有实现复制到具体类中,因此它也具有字节码级别的方法?否,TemplateImplementation没有继承方法的字节码。如果在TemplateImplementation上调用doSomething(),则Java VM在运行时会向后遍历类层次结构,直到找到实现为止。如果使用变通方法,它将在SpecializedTemplate中找到实现,在那里应用了方面(因为切入点匹配)。如果没有解决方法,它必须返回BaseTemplete,在那里没有应用方面(因为它与切入点不匹配)
@Component
public static class TemplateImplementation extends SpecializedTemplate {
    @Override
    void doOneStep() {
        implementationCalled = true;
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyConfig.class)
public class AopTest {
    @Configuration
    @EnableAspectJAutoProxy
    @ComponentScan(basePackageClasses = AopTest.class)
    public static class MyConfig {
    }
    ...
    @Override
    public void doSomething() {
        super.doSomething();
    }