根据环境变量或属性执行PointCut

我已经开发了一个很好的Spring Aspect ,我可以使用它监视我的服务操作性能。 如果某些操作需要很长时间才能执行,则会记录它们。

 @Aspect public class PerformanceMonitorAspect { private Logger logger = LoggerFactory.getLogger("performance"); @Pointcut("execution(* com.company.MyService+.*(..))") public void pointCut(){ } @Around("pointCut()") public Object profileServiceMethods(ProceedingJoinPoint thisJoinPoint) throws Throwable { MethodSignature ms = (MethodSignature) thisJoinPoint.getSignature(); Method m = ms.getMethod(); long t1 = System.nanoTime(); Object result = thisJoinPoint.proceed(); long t2 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t2 - t1); if (millis < 1000) { logger.trace("Execution time for {}: {} ms", m.getName(), millis); } else { logger.warn("Substantial execution time for {}: {} ms", m.getName(), millis); } return result; } } 

但是,由于它是一个@Around Advice,Spring会控制我的所有方法调用,以便对它们进行分析。 这在调试时有点不舒服(它甚至误导了Eclipse本身),所以我希望Pointcut只在我的应用程序处于生产阶段时执行。 我可以根据环境变量,Java属性或类似物来配置切入点有条件地执行吗?

文档仅涉及方法变量条件…提前感谢!

编辑

截至@ DavidL的建议,我将切入点改为:

 @Pointcut("execution(* com.tadic.module.TadicModuleGeneric+.*(..)) && if()") public static boolean pointCut() { return true; } 

这就是Eclipse不会对任何事情发出警告的方式。 但是,我在运行时得到这个:

 GRAVE: Critical error during deployment: java.lang.VerifyError: Expecting a stackmap frame at branch target 7 Exception Details: Location: com/mycompany/aspects/AuditAspect.()V @1: invokestatic Reason: Expected stackmap frame at this location. Bytecode: 0000000: 00b8 0134 a700 084b 2ab3 012f b1 Exception Handler Table: bci [1, 7] => handler: 7 at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2615) at java.lang.Class.getDeclaredMethods(Class.java:1860) at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:474) at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:458) at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:518) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:639) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:575) at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1350) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:355) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:326) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:434) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:624) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:461) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:410) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) 

所以看起来韦弗没有正确地做到这一点。 有什么建议?

编辑2当我通过基于Spring AOP代理的方面使用AspectJ时会发生此问题。 我正在使用Maven构建项目和Eclipse AspectJ插件以将其集成到我的工作区中。 AspectJ版本是1.8.2,Spring-AOP版本是3.2.8.RELEASE,我用Java 7.0.75 JDK构建它。

这是一个正在使用的POM的示例:

  4.0.0 com.tesicnor.test aspect-test 0.0.1-SNAPSHOT jar aspect-test http://maven.apache.org  UTF-8 1.7 1.7 1.8.2     org.codehaus.mojo aspectj-maven-plugin 1.7  1.7 1.7 1.7     compile         org.aspectj aspectjrt ${aspectj.version}   org.aspectj aspectjweaver ${aspectj.version}   org.springframework spring-aop 3.2.8.RELEASE    

这个POM是我创建的function测试用例的POM。 我目前的项目很庞大,似乎还有其他依赖导致了麻烦。

您可以获得表示当前阶段的属性(可能以静态方式)的引用。 根据它的值,您可以绕过profileServiceMethods方法中的代码(提前返回)。

在不太美观的方式中,您可以为了相同的目的在方面声明一个布尔变量:

 if(!logActivated) return null; else  

编辑:

只需看看文档。 也许你可以这样做:

 @Pointcut("execution(* com.company.MyService+.*(..)) && args(i) && if()") public static boolean pointCut(int i) { return i == State.PRODUCTION_STAGE ; } 

最后,我得到了它的工作。 似乎Eclipse在我的类路径中做了一些混乱,导致上面的问题。 我删除了aspectjweaver ,我可以根据@DavidL的答案得到以下代码:

 @Aspect public class PerformanceMonitorAspect { /** * Decide whether the Pointcut to be executed or not */ private static boolean enabled; @Pointcut("execution(* com.company.MyService+.*(..)) && if()") public static boolean pointCut() { return enabled; } private Logger logger = LoggerFactory.getLogger("performance"); @Around("pointCut()") public Object profileServiceMethods(ProceedingJoinPoint thisJoinPoint) throws Throwable { MethodSignature ms = (MethodSignature) thisJoinPoint.getSignature(); Method m = ms.getMethod(); long t1 = System.nanoTime(); Object result = thisJoinPoint.proceed(); long t2 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t2 - t1); if (millis < 1000) { logger.trace("Execution time for {}: {} ms", m.getName(), millis); } else { logger.warn("Substantial execution time for {}: {} ms", m.getName(), millis); } return result; } //The value is retrieved by Spring having read a config file written by Maven, depending on the profile @Value("${enable.performance.monitor}") public void setEnabled(boolean value) { enabled = value; } } 

然后,让Spring管理方面: