我遇到了一个奇怪的问题,我难以追踪。我有一个定义为@Aspect的类(ServiceErrorInterceptor),可通过XML配置将其实例化为单例bean。 XML配置允许我注入其依赖的bean。

在我正常的工作流程中,一切正常。方面类已正确实例化,并且每当调用建议时,注入的bean就是我所期望的。

但是,当我运行JUnit测试时,所有注入的bean均为空。这使我得出结论,建议是从不同的bean调用的,而不是由Spring实例化的同一个单例bean。为了进一步验证我的假设,我在实例化过程中调用的setter上放置了一个断点,如果我在建议中添加了一个断点,则会看到Bean ID与Bean ID不同。

我必须在我的JUnit类中启用一些特殊的配置来解决这个问题吗?我的测试课已经用以下注释:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "classpath:spring/applicationContext-base.xml",
        "classpath:spring/applicationContext-calculateServices.xml",
        "classpath:spring/applicationContext-dom.xml"})
public class LendingSimulationServiceImplTest {
...
...
}


我浏览了日志(启用了spring跟踪日志),但是看不到任何突出的地方。并且在此处发布整个日志可能会过分杀伤力。如果日志的特定部分有价值,请告诉我,我将其发布。

如果有帮助,我可以发布有关方面,我的junit和我的配置的代码。

application-context.xml代码段:

<!-- SPRING ASPECT BEAN.  POINTCUT DEFINED IN BEAN WITH ANNOTATION -->
<bean id="serviceErrorInterceptor" class="com.cws.cs.lendingsimulationservice.error.ServiceErrorInterceptor" scope="singleton">
    <property name="errorMessageProvider" ref="resourceBundleProviderImpl"/>
    <property name="defaultLocale">
        <util:constant static-field="java.util.Locale.ENGLISH" />
    </property>
</bean>


任何建议,将不胜感激。

编辑

我的bean实现为:

@Aspect
public class ServiceErrorInterceptor {

    /**
     * Logger
     */
    private static final Logger logger = LoggerFactory.getLogger(ServiceErrorInterceptor.class);

    /**
     * SOAP Header data
     */
    @Autowired
    private SOAPHeaderData soapHeaderData;

    public ServiceErrorInterceptor(){
        int x = 0;
        x=x+1;

    }

    /**
     * Exception Interceptor.
     * @param ex
     */
    @AfterThrowing(pointcut = "execution(* com.cws.cs.lendingsimulationservice.process.CalculatorProcess.calculate (..))", throwing = "ex")
    public void errorInterceptor(Exception ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Error Message Interceptor started");
        }

    }


pom的相关部分:

    <!-- Aspect Oriented Programming (AOP) Framework (depends on spring-core,
        spring-beans) Define this if you use Spring AOP APIs (org.springframework.aop.*) -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${org.springframework.version}</version>
    </dependency>

    <!-- Support for AspectJ Annotations -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>${org.aspectj}</version>
    </dependency>


我已经进行了进一步的调试,并在虚拟构造函数中放置了一个断点,得到以下结果:


通过@Aspect和XML配置,构造函数被调用两次(不同的bean id)
如果我删除@Aspect注释,则仅调用一次。
如果保留@Aspect却删除XML配置,那么甚至不会调用构造函数。
如果我将@Component批注与@Aspect结合使用(但没有任何XML配置),那么该bean将被构造两次。
然而,奇怪的是,同时使用@Component和@Aspect批注以及XML配置,该构造函数仍仅被调用两次。


那么,为什么同时具有XML配置和@Aspect注释会导致使用两个不同的bean id两次调用构造函数?

我进一步验证了,如果将整个AOP定义移动到XML配置中(删除@Aspect和@Pointcut批注),那么该bean仅被构造一次。

结束编辑

谢谢,

埃里克

最佳答案

除了@Aspect之外,您的方面是否有任何自动检测注释(@ Component,@ Service)等,如果有,这可能是为什么与您的定义中的bean一起存在的原因之一组态。

另外,只需扫描所有配置,以确保没有在其他地方声明此bean。

我知道,在Junit级别上不需要执行任何特殊操作。

关于java - JUnit编织错误的Spring AOP Bean,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10129929/

10-09 07:17
查看更多