我开发了一个不错的Spring Aspect
,我可以使用它来监视我的服务操作性能。如果某些操作需要很长时间才能执行,则会记录它们。根据环境变量或属性执行PointCut
@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
建议,春季需要以轮廓他们我所有的方法调用的控制。调试时这有点不舒服(它甚至会误导Eclipse本身),所以我希望仅当我的应用程序处于生产阶段时才执行Pointcut。我可以将Pointcut配置为根据环境变量,Java属性或类似条件有条件地执行吗?
Documentation只能引用方法变量条件......在此先感谢!
编辑
正如@ 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.<clinit>()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的样品:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tesicnor.test</groupId>
<artifactId>aspect-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>aspect-test</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<aspectj.version>1.8.2</aspectj.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.7</complianceLevel>
<source>1.7</source>
<target>1.7</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
</dependencies>
</project>
这POM是一个给我创建了一个功能性的测试用例。我目前的项目是巨大的,似乎还有其他依赖造成麻烦。
曾经有导致堆栈跟踪几个错误就像您在早期版本的AspectJ 1.8中关于Java 8一样。您能否告诉我您使用的是哪一种Java和AspectJ版本?你如何建立? Maven的?如果是这样,请显示POM。您是通过LTW还是CTW使用基于代理的Spring AOP或原生AspectJ?请提供更多信息,以便使问题可以重现。 – kriegaex 2015-03-14 13:27:10
你好@kriegaex。非常感谢您的关注,首先。实际上,如果我在Eclipse中创建一个新的工作区并从头开始构建测试用例,它就可以工作。所以看起来有些东西正在污染我的类路径。我将用请求的信息更新问题。 – 2015-03-16 07:37:57
我不明白为什么你需要* AspectJ Maven插件*用于Spring AOP。你只需要AspectJ,而不是Spring AOP,因为后者不会编译任何东西,只是使用动态代理。也许你试图一次以两种方式应用相同的方面。确实很奇怪。顺便说一下,* aspectjweaver.jar *仅用于AspectJ加载时编织,而不用于compile.time编织。无论如何,即使您使用AspectJ,在这种情况下也是多余的。 – kriegaex 2015-03-16 19:35:01