[SPRING] 환경 변수 또는 속성에 따라 PointCut 실행
SPRING환경 변수 또는 속성에 따라 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 속성 또는 similars에 따라 조건부로 실행되도록 Pointcut을 구성 할 수 있습니까?
문서는 메소드 변수 조건만을 참조합니다 ... 미리 감사드립니다!
편집하다
@ DavidL의 제안에 따라 필자는 pointcut을 다음과 같이 변경했습니다.
@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)
그래서 위버가 제대로하지 않는 것 같습니다. 어떤 제안?
EDIT 2 이 문제는 Spring AOP 프록시 기반 aspect를 통해 AspectJ를 사용할 때 발생한다. Maven을 사용하여 프로젝트를 빌드하고 이클립스 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은 제가 작성한 기능적인 테스트 케이스를위한 것입니다. 현재 진행중인 프로젝트는 거대하며 문제를 일으키는 다른 의존성이있는 것으로 보입니다.
해결법
-
==============================
1.현재 스테이지를 나타내는 속성에 대한 참조 (정적 인 방식으로)를 얻을 수 있습니다. 값에 따라 profileServiceMethods 메서드 내부에서 코드를 무시할 수 있습니다 (조기 반환).
현재 스테이지를 나타내는 속성에 대한 참조 (정적 인 방식으로)를 얻을 수 있습니다. 값에 따라 profileServiceMethods 메서드 내부에서 코드를 무시할 수 있습니다 (조기 반환).
덜 세련된 방식으로, 같은 목적을 위해 aspect에서 boolean var을 선언 할 수있다.
if(!logActivated) return null; else <your code here>
편집하다:
의사를 한번보세요. 어쩌면 이렇게 할 수 있습니다.
@Pointcut("execution(* com.company.MyService+.*(..)) && args(i) && if()") public static boolean pointCut(int i) { return i == State.PRODUCTION_STAGE ; }
-
==============================
2.마지막으로, 나는 그것을 작동 시켰습니다. 위의 문제를 일으키는 이클립스가 클래스 패스에서 다소 혼란을 일으키고있는 것 같습니다. 나는 aspectjweaver를 제거했고 @ DavidL의 답변에 기반하여 다음 코드를 사용할 수 있습니다.
마지막으로, 나는 그것을 작동 시켰습니다. 위의 문제를 일으키는 이클립스가 클래스 패스에서 다소 혼란을 일으키고있는 것 같습니다. 나는 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이 aspect를 관리하게합니다 :
<bean class="com.tadic.aspects.PerformanceMonitorAspect" factory-method="aspectOf" />
from https://stackoverflow.com/questions/29033690/executing-pointcut-depending-on-environment-variable-or-property by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 검색 폼에서 데이터 액세스 속도 향상 (0) | 2019.05.28 |
---|---|
[SPRING] 스프링 mvc 인터셉터를 사용하여 게시 된 값을 변경하는 방법 (0) | 2019.05.28 |
[SPRING] 목록에 자동로드 될 때의 빈 순서 (0) | 2019.05.28 |
[SPRING] Spring MVC에서 빈 문자열 대신에 형태 값을 NULL로 설정 (0) | 2019.05.28 |
[SPRING] Spring MVC에서 빈 폼 입력을 null 문자열로 바꾸는 쉬운 방법이 있습니까? (0) | 2019.05.28 |