我想監視具有指定註釋(比如說@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對JAX-RS註釋的切入點調用接口方法
- 4. AspectJ切入點類的列表中的所有方法
- 5. @AspectJ切入點與註釋
- 6. 如何匹配在AspectJ中沒有特定註釋的方法
- 7. AspectJ切入點在特定方法中的方法調用
- 8. Spring AOP:帶有@Transactional註釋方法的方法的註釋切入點?
- 9. @AspectJ切入點的方法是與註釋覆蓋的接口方法
- 10. 與註釋AspectJ切入點參數
- 11. 如何對具有特定註釋的方法的類進行內部類型注入?
- 12. AspectJ切入點從另一個特定的方法
- 13. 如何找到所有具有特定註釋的Java對象(不是類)?
- 14. 如何獲得具有特定註釋的所有方法的javadoc,方法名稱和包/類名稱?
- 15. Spring AOP,切入點表達式:具有特定參數的註釋
- 16. 切入點,以配合特定的PARAMS標註的方法來註釋
- 17. Aspectj匹配切入點,但不關心方法級別的註釋參數
- 18. 帶有特定方法調用方法的切入點
- 19. AspectJ - 帶有動態值的切入點
- 20. 地圖註釋顯示所有點的所有圖像/針腳
- 21. Compell與特定的註釋的方法以具有特定參數/簽名
- 22. 針對特定註釋方法的Spring引導異常處理
- 23. 針對基於Spring和AspectJ的類的基於註釋的方面
- 24. AspectJ - 加載時織入,私有方法JRE類的加載時編織,特權方面和切入點
- 25. 註釋使私有方法只針對測試類別公開
- 26. 的AspectJ獲取對象切入點
- 27. 幫助切入點 - AspectJ的
- 28. 計數具有註釋的類和方法的數量
- 29. Spring AOP - 帶註釋的每種方法的切入點
- 30. Aspectj @Around切割在Java中的所有方法
下面的一個工程的延伸。 @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