@AspectJ punto de corte para todos los métodos de una clase con anotación específica

Quiero monitorear todos los métodos públicos de todas las clases con la anotación especificada (digamos @Monitor) (nota: la anotación es a nivel de clase). ¿Cuál podría ser un punto de corte posible para esto? Nota: Estoy usando @AspectJ style Spring AOP.

    Debe combinar un punto de corte con un punto de corte de método.

    Estos puntos harán el trabajo de encontrar todos los métodos públicos dentro de una clase marcada con una anotación @Monitor:

    @Pointcut("within(@org.rejeev.Monitor *)") public void beanAnnotatedWithMonitor() {} @Pointcut("execution(public * *(..))") public void publicMethod() {} @Pointcut("publicMethod() && beanAnnotatedWithMonitor()") public void publicMethodInsideAClassMarkedWithAtMonitor() {} 

    Asesoramiento en el último pointcut que combina los dos primeros y listo.

    Si está interesado, he escrito una hoja de trucos con el estilo @AspectJ aquí con un documento de ejemplo correspondiente aquí.

    Usando anotaciones, como se describe en la pregunta.

    Anotación: @Monitor

    Anotación en clase, app/PagesController.java :

     package app; @Controller @Monitor public class PagesController { @RequestMapping(value = "/", method = RequestMethod.GET) public @ResponseBody String home() { return "w00t!"; } } 

    Anotación sobre el método, app/PagesController.java :

     package app; @Controller public class PagesController { @Monitor @RequestMapping(value = "/", method = RequestMethod.GET) public @ResponseBody String home() { return "w00t!"; } } 

    Anotación personalizada, app/Monitor.java :

     package app; @Component @Target(value = {ElementType.METHOD, ElementType.TYPE}) @Retention(value = RetentionPolicy.RUNTIME) public @interface Monitor { } 

    Aspecto para la anotación, app/MonitorAspect.java :

     package app; @Component @Aspect public class MonitorAspect { @Before(value = "@within(app.Monitor) || @annotation(app.Monitor)") public void before(JoinPoint joinPoint) throws Throwable { LogFactory.getLog(MonitorAspect.class).info("monitor.before, class: " + joinPoint.getSignature().getDeclaringType().getSimpleName() + ", method: " + joinPoint.getSignature().getName()); } @After(value = "@within(app.Monitor) || @annotation(app.Monitor)") public void after(JoinPoint joinPoint) throws Throwable { LogFactory.getLog(MonitorAspect.class).info("monitor.after, class: " + joinPoint.getSignature().getDeclaringType().getSimpleName() + ", method: " + joinPoint.getSignature().getName()); } } 

    Habilite AspectJ, servlet-context.xml :

      

    Incluye las bibliotecas de AspectJ, pom.xml :

     spring-aop aspectjrt aspectjweaver cglib 

    Algo como eso:

     @Before("execution(* com.yourpackage..*.*(..))") public void monitor(JoinPoint jp) { if (jp.getTarget().getClass().isAnnotationPresent(Monitor.class)) { // perform the monitoring actions } } 

    Tenga en cuenta que no debe haber ningún otro consejo en la misma clase antes de este, ya que las anotaciones se perderán después del proxy.

    Utilizar

     @Before("execution(* (@YourAnnotationAtClassLevel *).*(..))") public void beforeYourAnnotation(JoinPoint proceedingJoinPoint) throws Throwable { } 

    También puede definir el punto de corte como

     public pointcut publicMethodInsideAClassMarkedWithAtMonitor() : execution(public * (@Monitor *).*(..)); 

    debería ser suficiente para marcar su método de aspecto de esta manera:

     @After("@annotation(com.marcot.CommitTransaction)") public void after() { 

    eche un vistazo a esto para obtener una guía paso a paso sobre esto.

    La forma más simple parece ser:

     @Around("execution(@MyHandling * com.exemple.YourService.*(..))") public Object aroundServiceMethodAdvice(final ProceedingJoinPoint pjp) throws Throwable { // perform actions before return pjp.proceed(); // perform actions after } 

    Interceptará la ejecución de todos los métodos específicamente anotados con ‘@MyHandling’ en la clase ‘YourService’. Para interceptar todos los métodos sin excepción, simplemente coloque la anotación directamente en la clase.

    No importa el scope público / privado aquí, pero tenga en cuenta que Spring-Aop no puede usar el aspecto de las llamadas a métodos en la misma instancia (típicamente las privadas), ya que no utiliza la clase proxy en este caso.

    Utilizamos el consejo de @Around aquí, pero básicamente es la misma syntax con @Before, @After o cualquier consejo.

    Por cierto, la anotación @MyHandling debe configurarse así:

     @Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.METHOD, ElementType.TYPE }) public @interface MyHandling { } 

    Puede usar el intérprete de monitoreo de rendimiento de Spring y registrar el consejo de forma programática utilizando un procesador de beanpost.

     @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Monitorable { } public class PerformanceMonitorBeanPostProcessor extends ProxyConfig implements BeanPostProcessor, BeanClassLoaderAware, Ordered, InitializingBean { private Class< ? extends Annotation> annotationType = Monitorable.class; private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); private Advisor advisor; public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; } public int getOrder() { return LOWEST_PRECEDENCE; } public void afterPropertiesSet() { Pointcut pointcut = new AnnotationMatchingPointcut(this.annotationType, true); Advice advice = getInterceptor(); this.advisor = new DefaultPointcutAdvisor(pointcut, advice); } private Advice getInterceptor() { return new PerformanceMonitoringInterceptor(); } public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) { if(bean instanceof AopInfrastructureBean) { return bean; } Class< ?> targetClass = AopUtils.getTargetClass(bean); if(AopUtils.canApply(this.advisor, targetClass)) { if(bean instanceof Advised) { ((Advised)bean).addAdvisor(this.advisor); return bean; } else { ProxyFactory proxyFactory = new ProxyFactory(bean); proxyFactory.copyFrom(this); proxyFactory.addAdvisor(this.advisor); return proxyFactory.getProxy(this.beanClassLoader); } } else { return bean; } } } 

    De Spring’s AnnotationTransactionAspect :

     /** * Matches the execution of any public method in a type with the Transactional * annotation, or any subtype of a type with the Transactional annotation. */ private pointcut executionOfAnyPublicMethodInAtTransactionalType() : execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);