根据环境变量或属性执行PointCut [英] Executing PointCut depending on Environment variable or property

查看:1578
本文介绍了根据环境变量或属性执行PointCut的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've developed a nice Spring Aspect which I can use to monitor my service operations performance. If some operations are taking a long time to execute, it logs them.

@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 建议,Spring控制我所有的方法调用,以便对其进行配置。这在调试时有点不舒服(甚至误导Eclipse本身),所以只有当我的应用程序在生产阶段时,我才想要执行Pointcut。可以根据环境变量,Java属性或类似条件将Pointcut配置为有条件地执行?

However, as it's an @Around Advice, Spring takes control of all my method calls in order to profile them. That's a bit uncomfortable while debugging (it even misleads Eclipse itself), so I would like the Pointcut to be executed only when my application is at production stage. Can I configure the Pointcut to be conditionally executed depending on a an enviroment variable, Java property or similars?

文档仅指方法变量条件...提前感谢!

Documentation only refers to method variable conditions... Thanks in advance!

编辑

根据@ DavidL的建议,我改变了我的切入点:

As of @DavidL's suggestion, I changed my pointcut to this:

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

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

That's the way Eclipse doesn't warn about anything. However, I get this at runtime:

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)

所以看起来织工没有做到这一点。任何建议?

So it seems the weaver isn't doing it properly. Any suggestions?

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

EDIT 2 This issue happens when I use AspectJ via Spring AOP proxy-based aspects. I'm using Maven to build the project and Eclipse AspectJ plugin to integrate it in my workspace. AspectJ version is 1.8.2, Spring-AOP version is 3.2.8.RELEASE and I'm building it with the Java 7.0.75 JDK.

这里是一个正在使用的POM样本:

Here it is a sample of the POM being used:

<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是我创建的功能测试用例。我目前的项目是巨大的,似乎有其他依赖性导致了麻烦。

This POM is the one for a functional testcase I created. My current project is huge and seems that there's other dependency causing the trouble.

推荐答案

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

Finally, I got it working. It seems Eclipse is doing some mess in my classpath, causing the problem above. I removed the aspectjweaver and I can get work the following code, based in @DavidL's answer:

@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管理方面:

Then, let Spring manage the aspect:

<bean class="com.tadic.aspects.PerformanceMonitorAspect" factory-method="aspectOf" />

这篇关于根据环境变量或属性执行PointCut的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆