为静态方法设置AspectJ建议

izh*_*sin 7 java aspectj spring-aop

我用原始的Pointcut和Advise方法编写了简单的Aspect:

@Aspect
public class MyAspect {

  @Pointcut("execution(static * com.mtag.util.SomeUtil.someMethod(..))")
  public void someMethodInvoke() { }

  @AfterReturning(value = "someMethodInvoke())", returning = "comparisonResult")
  public void decrementProductCount(List<String> comparisonResult) {
    //some actions
  }
}
Run Code Online (Sandbox Code Playgroud)

我有以下基于Spring注释的应用程序配置:

@Configuration
@EnableAspectJAutoProxy
public class AppConfig { 
  //...
}
Run Code Online (Sandbox Code Playgroud)

和com.mtag.util包中的实用程序类:

public class SomeUtil {
  static List<String> someMethod(List<String> oldList, List<String> newList) {
    //...
  } 
}
Run Code Online (Sandbox Code Playgroud)

但是当我打电话的时候

SomeUtil.someMethod(arg1, arg2);
Run Code Online (Sandbox Code Playgroud)

在单元测试中我可以看到方法调用没有被截获,我的@AfterReturning建议不起作用.

但是如果我将someMethod()类型更改为实例(非静态)方法,则切入到

@Pointcut("execution(* com.mtag.util.SomeUtil.someMethod(..))")
Run Code Online (Sandbox Code Playgroud)

并通过添加@Component注释来管理SomeUtil bean并调用目标metod,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppConfig.class}, loader = AnnotationConfigContextLoader.class)
public class SomeUtilTest {

    @Autowired
    private SomeUtil someUtil;

    @Test
    public void categoriesDiffCalc() {
        List<String> result = someUtil.someMethod(...);
    }
}
Run Code Online (Sandbox Code Playgroud)

一切都好.

我以什么方式为静态方法设置建议?

Eug*_*kov 8

实际上,在Spring框架中没有使用自动代理拦截静态方法的解决方案.您应该使用LWT AspectJ解决方案.

简而言之,您应该使用相同的注释,但需要一些额外的配置.

1)在下一行添加到spring上下文文件:

<context:load-time-weaver/>
Run Code Online (Sandbox Code Playgroud)

(可能在你的情况下没有必要)

2)遗憾的是你还应该添加META-INF/aop.xml.例:

<weaver>
    <include within="com.example.ClassA"/> <!-- path to concrete class -->
    <include within="com.log.* "/> <!—- path to aspects package -->
</weaver>
<aspects>
    <aspect name="com.log.AspectA"/>
</aspects>
Run Code Online (Sandbox Code Playgroud)

3)启动JVM时的参数

-javaagent:${PATH_TO_LIB }/aspectjweaver.jar
Run Code Online (Sandbox Code Playgroud)

应该补充.

所以这个解决方案相当费力.

有关更多信息,请参阅此处的7.8.4章节http://docs.spring.io/spring/docs/3.0.0.RC2/reference/html/ch07s08.html

  • 很好的答案,尤金.我甚至认为这个解决方案很费力.一旦设置它将永远工作.:-) Anway,如果你想避免额外的运行时配置,你仍然可以使用编译时编织. (2认同)
  • 是的,我的意思是这个解决方案很费力,依赖于拦截非静态方法,但对我来说,调查起来很费力。=) (2认同)
  • @Kwadz,您可以将CTW与AspectJ一起使用,那么您就不再需要Spring AOP。但是,如果那是您的问题,那么您仍然可以在其他方面使用Spring AOP。 (2认同)