我想监视具有指定注释(比如说@Monitor)的所有类的所有公共方法(注意:注释在类级别)。对此可能有什么切入点? 注意:我使用@AspectJ风格的Spring AOP。@AspectJ针对具有特定注释的类的所有方法的切入点
回答
类似的东西:
@Before("execution(* com.yourpackage..*.*(..))")
public void monitor(JoinPoint jp) {
if (jp.getTarget().getClass().isAnnotationPresent(Monitor.class)) {
// perform the monitoring actions
}
}
请注意,你不能此人之前都在同一类任何其他建议,因为注释将进行代理后丢失。
你应该结合一个类型切入点和方法切入点。
这些切入点就做好找到标有注释@Monitor一个类中的所有公共方法:
@Pointcut("within(@org.rejeev.Monitor *)")
public void beanAnnotatedWithMonitor() {}
@Pointcut("execution(public * *(..))")
public void publicMethod() {}
@Pointcut("publicMethod() && beanAnnotatedWithMonitor()")
public void publicMethodInsideAClassMarkedWithAtMonitor() {}
咨询最后切入点,结合了前两个,你就大功告成了!
如果你有兴趣,我写了一个cheat sheet与@AspectJ风格在这里与相应的example document在这里。
谢谢。讨论您的备忘单中的注释切入点特别有用。 – GregHNZ 2013-02-07 22:11:03
我如何在建议中获得对类的引用我使用正常的切入点建议的方式是 @Before(“onObjectAction()&& this(obj)”) – expressions 2013-07-29 07:35:50
该备忘单非常有帮助,即使已经5年:) – 2015-02-19 13:16:44
您也可以定义为切入点
public pointcut publicMethodInsideAClassMarkedWithAtMonitor() : execution(public * (@Monitor *).*(..));
简单一点''执行(public * @Monitor *。*(..))'也可以。 – xmedeko 2014-12-19 09:12:23
最简单的方法似乎是:
@Around("execution(@MyHandling * com.exemple.YourService.*(..))")
public Object aroundServiceMethodAdvice(final ProceedingJoinPoint pjp)
throws Throwable {
// perform actions before
return pjp.proceed();
// perform actions after
}
它将拦截与“YourService” @MyHandling“特别注释的所有方法执行类。要毫无例外地拦截所有方法,只需将注释直接放在类上即可。
不管这里的私有/公共范围如何,但请记住,spring-aop不能在同一个实例中使用aspect方法调用(通常是私有方法),因为在这种情况下它不使用代理类。
我们在这里使用@Around的建议,但它基本上与@Before,@After或任何建议相同的语法。
顺便提一下,@MyHandling注释必须配置是这样的:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface MyHandling {
}
这是不回答原来的声明,与ElementType.Type – Alex 2012-05-15 00:07:28
是的,ElementType.TYPE也将允许直接放在类上的注释,我想,将导致处理这个类中的任何方法。我真的吗?它真的有用吗? – Donatello 2012-05-24 12:26:47
'//执行'后面的动作将永远不会被调用,因为我们之前返回行中的值。 – josephpconley 2017-04-21 15:34:01
使用注释,如在问题说明。
译注:@Monitor
诠释类,app/PagesController.java
:
package app;
@Controller
@Monitor
public class PagesController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody String home() {
return "w00t!";
}
}
上方法注释,app/PagesController.java
:
package app;
@Controller
public class PagesController {
@Monitor
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody String home() {
return "w00t!";
}
}
自定义注释,app/Monitor.java
:
package app;
@Component
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Monitor {
}
看点的注释,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());
}
}
启用AspectJ的,servlet-context.xml
:
<aop:aspectj-autoproxy />
包括AspectJ库,pom.xml
:
<artifactId>spring-aop</artifactId>
<artifactId>aspectjrt</artifactId>
<artifactId>aspectjweaver</artifactId>
<artifactId>cglib</artifactId>
不错的例子。一个问题:为什么Annotation'Monitor'必须是Spring'Component'? – mwhs 2013-11-22 16:36:14
'Component'注释用于告诉Spring容器应用AspectJ weaver中包含的类。默认情况下,Spring只查看'Controller','Service'和其他特定的注释,而不是'Aspect'。 – Alex 2013-11-22 20:46:45
好的,谢谢。但是我在讨论'@ interface'上的'@ Component'注释而不是'Aspect'。为什么需要? – mwhs 2013-11-23 19:18:43
你可以使用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;
}
}
}
应该足够,以纪念你的一方面方法是这样的:
@After("@annotation(com.marcot.CommitTransaction)")
public void after() {
看看this对这样的一步一步的指导。
从Spring的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 *);
使用
@Before("execution(* (@YourAnnotationAtClassLevel *).*(..))")
public void beforeYourAnnotation(JoinPoint proceedingJoinPoint) throws Throwable {
}
- 1. 注释私有方法的AspectJ切入点
- 2. @AspectJ切入点与注释
- 3. @AspectJ切入点的方法是与注释覆盖的接口方法
- 4. 与注释AspectJ切入点参数
- 5. AspectJ切入点从另一个特定的方法
- 6. 如何对具有特定注释的方法的类进行内部类型注入?
- 7. 如何获得具有特定注释的所有方法的javadoc,方法名称和包/类名称?
- 8. 带有特定方法调用方法的切入点
- 9. 针对特定注释方法的Spring引导异常处理
- 10. AspectJ - 加载时织入,私有方法JRE类的加载时编织,特权方面和切入点
- 11. 搜索特定注释类型的所有实例
- 12. 如何为@Service所注解的类的所有方法编写切入点并返回类型void
- 13. 如何忽略具有特定注释的方法的checkstyle javadoc警告
- 14. eclipse可以找到具有特定注释的方法签名的出现吗?
- 15. 针对特定的jQuery元素具有相同的类名
- 16. 针对采取复杂类型的方法的Web API注释?
- 17. 使用org.refelections获取具有注释的类方法
- 18. 有没有更好的方法来切换注释代码?
- 19. 匹配具有特定参数的切入点
- 20. Java - 方法中的对象参数必须具有@Entity注释
- 21. 具有带注释参数的私有方法的Android java.lang.VerifyError
- 22. 查找具有自定义注释的所有bean
- 23. xsl删除所有节点的注释
- 24. Spring AspectJ从ProceedingJoinPoint获取方法注释
- 25. AspectJ - 在本地方法调用上的切入点
- 26. 的AspectJ LTW在eclipse - 切入点不与静态方法
- 27. 将具有nsIDOMGlobalPropertyInitializer的对象注入到特定页面
- 28. AspectJ的表注释发出
- 29. AspectJ:如何替换现有注释
- 30. 针对列表的F#类型注释
下面的一个工程的延伸。 @Pointcut(“execution(*(@ org.rejeev.Monitor *)。*(..))”) 但是现在这个建议正在执行两次。任何线索? – 2010-01-06 08:32:01
另一点是@Monitor注释位于一个接口上,并有一个类实现它。接口和类的存在是否会导致这种建议的双重执行? – 2010-01-06 12:18:57
你应该接受下面的优秀答案。这给他的声誉。这里有很少的人可以回答AspectJ的问题。 – fool4jesus 2013-11-12 17:38:38