@AspectJ pointcut for all methods of a class with

2019-01-04 05:53发布

I want to monitor all public methods of all Classes with specified annotation (say @Monitor) (note: Annotation is at class level). What could be a possible pointcut for this? Note: I am using @AspectJ style Spring AOP.

9条回答
看我几分像从前
2楼-- · 2019-01-04 05:53

The simplest way seems to be :

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

   return pjp.proceed();

   // perform actions after
}

It will intercept execution of all methods specifically annotated with '@MyHandling' in 'YourService' class. To intercept all methods without exception, just put the annotation directly on the class.

No matter of the private / public scope here, but keep in mind that spring-aop cannot use aspect for method calls in same instance (typically private ones), because it doesn't use the proxy class in this case.

We use @Around advice here, but it's basically the same syntax with @Before, @After or any advice.

By the way, @MyHandling annotation must be configured like this :

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

}
查看更多
爷、活的狠高调
3楼-- · 2019-01-04 05:57

You could use Spring's PerformanceMonitoringInterceptor and programmatically register the advice using a beanpostprocessor.

@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;
    }
  }
}
查看更多
迷人小祖宗
4楼-- · 2019-01-04 06:02

Something like that:

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

Note that you must not have any other advice on the same class before this one, because the annotations will be lost after proxying.

查看更多
相关推荐>>
5楼-- · 2019-01-04 06:08

You can also define the pointcut as

public pointcut publicMethodInsideAClassMarkedWithAtMonitor() : execution(public * (@Monitor *).*(..));
查看更多
beautiful°
6楼-- · 2019-01-04 06:10

it should be enough to mark your aspect method like this:

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

have a look at this for a step by step guide on this.

查看更多
劳资没心,怎么记你
7楼-- · 2019-01-04 06:11

You should combine a type pointcut with a method pointcut.

These pointcuts will do the work to find all public methods inside a class marked with an @Monitor annotation:

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

@Pointcut("execution(public * *(..))")
public void publicMethod() {}

@Pointcut("publicMethod() && beanAnnotatedWithMonitor()")
public void publicMethodInsideAClassMarkedWithAtMonitor() {}

Advice the last pointcut that combines the first two and you're done!

If you're interested, I have written a cheat sheet with @AspectJ style here with a corresponding example document here.

查看更多
登录 后发表回答