我有一个带有以下Spring(4.0.6.RELEASE)配置的现有WAR:
<beans>
<context:annotation-config/>
<context:component-scan base-package="org.example"/>
</beans>
在这个应用程序中,我添加了以下注释界面(逐字复制):
package org.example;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface Logged {}
以下Aspect类(也是逐字复制的):
package org.example;
@Aspect
@Component
public class LoggingAspect
{
@Before("@annotation(Logged)")
public void before()
{
System.out.println("LoggingAspect.before()");
}
}
和以下批处理类(逐字复制):
package org.example;
@Component
public class Batch
{
@Logged
@Scheduled(fixedDelay = 100)
public void execute()
{
System.out.println("Batch.execute()");
}
}
然后将Spring配置更改为:
<beans>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:annotation-config/>
<context:component-scan base-package="org.example"/>
<task:annotation-driven executor="executor" scheduler="scheduler"/>
<task:executor id="executor" pool-size="5"/>
<task:scheduler id="scheduler" pool-size="5"/>
</beans>
我希望在控制台上看到以下消息:
LoggingAspect.before()
Batch.execute()
但是,我只看到第二条消息(即没有调用方面代码)。
我把这个代码带到了一个示例应用程序,有趣的是这两个消息在示例应用程序中显得很好。然后,我将实际应用程序中的每个文件与示例进行比较,并确保一切都完全相同,包括类和文件名。然而,这方面在实际应用中不起作用。
在两个应用程序中打开调试级别日志记录后,示例应用程序将显示以下日志消息:
DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void org.example.LoggingAspect.before()
但实际应用程序没有此日志消息。这似乎表明示例应用程序检测到方面方法,但实际的应用程序没有。两者都使用相同的Spring和AspectJ版本(分别为4.0.6.RELEASE和1.8.1)。两个日志都没有错误。
Spring在两种情况下实例化LoggingAspect
(从日志中收集)。
我还检查了两个应用程序的各种JAR依赖关系,一切都是一样的,除了实际的应用程序使用的是示例应用程序没有的Spring ORM,Hibernate和EHCACHE JAR。
任何关于应该检查其他内容的指针都很有用。
答案 0 :(得分:0)
尽管调试应用程序数月,升级和降级各种Spring和AspectJ版本,但问题无法解决。有趣的是,从受影响的类创建的示例应用程序没有显示任何问题。
我必须通过在Spring配置中指定方面来解决问题。这一行:
<aop:aspectj-autoproxy proxy-target-class="true"/>
必须改为:
<aop:aspectj-autoproxy proxy-target-class="true">
<aop:include name="loggingAspect"/>
</aop:aspectj-autoproxy>
在这种情况下,loggingAspect
是Spring框架为bean类LoggingAspect
的实例分配的默认bean名称。如果bean名称设置为其他值,则该值必须与<aop:include />
一起使用。