Java @AspectJ 切入点用于具有特定注释的类的所有方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2011089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@AspectJ pointcut for all methods of a class with specific annotation
提问by Rejeev Divakaran
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.
我想用指定的注释(比如@Monitor)监视所有类的所有公共方法(注意:注释是在类级别)。这可能是什么切入点?注意:我使用的是@AspectJ 风格的 Spring AOP。
回答by Bozho
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 beforethis one, because the annotations will be lost after proxying.
请注意,在此之前,您不能对同一类有任何其他建议,因为代理后注释将丢失。
回答by Espen
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:
这些切入点将完成在标有 @Monitor 注释的类中查找所有公共方法的工作:
@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 sheetwith @AspectJ style here with a corresponding example documenthere.
回答by Shekhar
You can also define the pointcut as
您还可以将切入点定义为
public pointcut publicMethodInsideAClassMarkedWithAtMonitor() : execution(public * (@Monitor *).*(..));
回答by Donatello
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.
它将拦截在“YourService”类中用“@MyHandling”特别注释的所有方法的执行。要无一例外地拦截所有方法,只需将注解直接放在类上即可。
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.
无论这里的私有/公共范围如何,但请记住,spring-aop 不能在同一实例(通常是私有的)中对方法调用使用方面,因为在这种情况下它不使用代理类。
We use @Around advice here, but it's basically the same syntax with @Before, @After or any advice.
我们在这里使用@Around 建议,但它与@Before、@After 或任何建议的语法基本相同。
By the way, @MyHandling annotation must be configured like this :
顺便说一句,@MyHandling 注释必须像这样配置:
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.TYPE })
public @interface MyHandling {
}
回答by Alex
Using annotations, as described in the question.
使用注释,如问题中所述。
Annotation: @Monitor
注解: @Monitor
Annotation on class, app/PagesController.java
:
类注释,app/PagesController.java
:
package app;
@Controller
@Monitor
public class PagesController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody String home() {
return "w00t!";
}
}
Annotation on method, app/PagesController.java
:
方法注释,app/PagesController.java
:
package app;
@Controller
public class PagesController {
@Monitor
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody String home() {
return "w00t!";
}
}
Custom annotation, app/Monitor.java
:
自定义注释,app/Monitor.java
:
package app;
@Component
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Monitor {
}
Aspect for annotation, app/MonitorAspect.java
:
注释方面,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());
}
}
Enable AspectJ, servlet-context.xml
:
启用AspectJ的,servlet-context.xml
:
<aop:aspectj-autoproxy />
Include AspectJ libraries, pom.xml
:
包括 AspectJ 库,pom.xml
:
<artifactId>spring-aop</artifactId>
<artifactId>aspectjrt</artifactId>
<artifactId>aspectjweaver</artifactId>
<artifactId>cglib</artifactId>
回答by Vikram
You could use Spring's PerformanceMonitoringInterceptor and programmatically register the advice using a beanpostprocessor.
您可以使用 Spring 的 PerformanceMonitoringInterceptor 并使用 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;
}
}
}
回答by marcocast
回答by xmedeko
From Spring's AnnotationTransactionAspect
:
从春天的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 *);
回答by Davide Consonni
Use
用
@Before("execution(* (@YourAnnotationAtClassLevel *).*(..))")
public void beforeYourAnnotation(JoinPoint proceedingJoinPoint) throws Throwable {
}