Я помогаю моей команде разработчиков с некоторым кодом регистрации в нашей среде.
с использованием весеннего AOP Я создал классный класс, называемый LoggingAspect.Его основная цель - записывать время выполнения методов для классов в каталогах com.zions.comon.services.logging и снабжать их комментариями @ Loggable.
Поскольку некоторые классы уже имеют журналирование @ sl4j, мне нужно определить, нет ли в журнале члена журнала.объекты существуют и используют встроенную регистрацию @ slf4j для этого класса.Если это не так, мне нужно выполнить аннотацию @ sl4j в коде регистрации аспектов.
Первый оператор в блоке try проверит, существует ли элемент журнала для объекта.Если это так, то iLog будет настроен на регистратор входящего объекта.Однако я не уверен, как завершить остальную часть кода, как только я обнаружу объект члена журнала.Я не ожидаю, что кто-то напишет этот код для меня, но был бы признателен за любые предложения / области исследования о том, как это сделать - например, использование «если»
Логика должна выглядеть примерно так:
- Перехватывать и вычислять время ведения журнала метода в выбранных классах
- Проверять существующий объект члена журнала, который указывает, что @ slf4j уже присутствует в классе
- Если объект члена журнала завершается, используйте ведение журнала @ sl4jфункции, уже встроенные в этот класс
- Если объект-член журнала не существует, используйте @ slf4j, регистрируясь в журнале Аспект-код.
любая помощь будет оценена
"схема потока регистрации"
Возвращенный код к исходной версии - код My LoggingAspect на данный момент выглядит следующим образом
package com.zions.common.services.logging
import groovy.util.logging.Slf4j
import org.slf4j.Logger
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.EnableAspectJAutoProxy
@Aspect
@Configuration
@Slf4j
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class LoggingAspect {
*
* This is a Logging Aspect for the Loggable annotation that calculates method runtimes
* for all methods under classes annotated with @Loggable*/
/**
* Logs execution time of method under aspect.
*
* @param joinPoint - method under join
* @return actual return of method under join point.
* @throws Throwable
*/
@Around('execution (* *(..)) && !execution(* *.getMetaClass()) && @within(com.zions.common.services.logging.Loggable)')
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
def obj = joinPoint.this
Logger iLog = log
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - start;
try {
/*First statement of try block attempts to test if log members exist on object.
If it does, then iLog will get set to incoming object's logger*/
obj.log.isInfoEnabled()
iLog = obj.log
} catch (e) {}
iLog.info("${joinPoint.getSignature()} executed in ${executionTime}ms");
return proceed;
}
}
Если это полезномоя запись в журнале:
package com.zions.common.services.logging
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/* Logging annotation to be used at class level
* Loggable annotation for all methods of a class annotated with the @Loggable annotation*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {}
Я добавил тестовый класс junit, который проверяет, когда член журнала найден - строка 'iLog = obj.log' get вызывается из кода LoggingAspect и т.st is PASSING.
LoggingAspectSpecification.groovy
package com.zions.common.services.logging
import static org.junit.Assert.*
import groovy.util.logging.Slf4j
import org.junit.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Profile
import org.springframework.context.annotation.PropertySource
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
@ContextConfiguration(classes=[LoggingAspectSpecificationConfig])
class LoggingAspectSpecification extends Specification {
@Autowired
SomeClass someClass
def 'Main flow for timing log'() {
setup: 'class to be logged'
when: 'execute something with class testing log'
someClass.methodOne()
someClass.methodTwo()
then: 'validate something logged'
true
}
}
@TestConfiguration
@Profile("test")
@ComponentScan(["com.zions.common.services.logging"])
@PropertySource("classpath:test.properties")
class LoggingAspectSpecificationConfig {
@Bean
SomeClass someClass() {
return new SomeClass()
}
}
@Loggable
@Slf4j
class SomeClass {
def methodOne() {
log.info('run methodOne')
}
def methodTwo() {
log.info('run methodTwo')
}
}
Однако мой модульный тест не выполняется с классами, которые не имеют @ Slf4j, что означает, что он будет выполняться с регистраторомаспект вместо объекта pointcut.Полная трассировка ошибок:
groovy.lang.MissingPropertyException: No such property: log for class: com.zions.common.services.logging.SomeClass2
at com.zions.common.services.logging.SomeClass2.methodOne(LoggingAspectSpecification2.groovy:55)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
at com.zions.common.services.logging.LoggingAspect.logExecutionTime(LoggingAspect.groovy:42)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:643)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:632)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:174)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.zions.common.services.logging.LoggingAspectSpecification2.Main flow for timing log(LoggingAspectSpecification2.groovy:27)
Второй код модульного теста приведен ниже - (единственное отличие состоит в том, что @ Slf4j) отсутствует в классах.
LoggingAspectSpecification2.groovy
package com.zions.common.services.logging
import static org.junit.Assert.*
import groovy.util.logging.Log
import groovy.util.logging.Slf4j
import org.junit.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Profile
import org.springframework.context.annotation.PropertySource
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
@ContextConfiguration(classes=[LoggingAspectSpecificationConfig2])
class LoggingAspectSpecification2 extends Specification {
@Autowired
SomeClass2 someClass2
def 'Main flow for timing log'() {
setup: 'class to be logged'
when: 'execute something with class testing log'
someClass2.methodOne()
someClass2.methodTwo()
then: 'validate something logged'
true
}
}
<!-- language: lang-groovy -->
@TestConfiguration
@Profile("test")
@ComponentScan(["com.zions.common.services.logging"])
@PropertySource("classpath:test.properties")
class LoggingAspectSpecificationConfig2 {
@Bean
SomeClass2 someClass2() {
return new SomeClass2()
}
}
<!-- language: lang-groovy -->
@Loggable
class SomeClass2 {
def methodOne() {
int x=10, y=20;
System.out.println(x+y+" testing the aspect logging code");
}
def methodTwo() {
int x=10, y=20;
System.out.println(x+y+" testing the aspect logging code");
}
}
Я предполагаю, что что-то не так в моем коде LoggingAspect в блоке Try Catch?