【问题标题】:@AspectJ pointcut for all methods inside package包内所有方法的@AspectJ 切入点
【发布时间】:2014-11-17 11:50:21
【问题描述】:

我有一个特定包的工作代码,但我想为所有 controllersservicedao 包配置它 例如

  • com.abc.xyz.content.controller
  • com.abc.xyz.content.service
  • com.abc.xyz.content.dao
  • com.abc.xyz.category.controller
  • com.abc.xyz.category.service
  • com.abc.xyz.category.dao

等等。 . . 那是我项目的基本包,有人可以帮助我如何去做,以便它适用于我的网络项目的所有类,包括控制器,在此先感谢。 . .

package com.abc.xyz.utilities;

import java.util.Arrays;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect
{
    private Log log = LogFactory.getLog(this.getClass());

    @Pointcut("execution(* com.abc.xyz.content.service..*(..))")
    protected void loggingOperation()
    {
    }

    @Before("loggingOperation()")
    @Order(1)
    public void logJoinPoint(JoinPoint joinPoint)
    {
    log.info("Signature declaring type : " + joinPoint.getSignature().getDeclaringTypeName());
    log.info("Signature name : " + joinPoint.getSignature().getName());
    log.info("Arguments : " + Arrays.toString(joinPoint.getArgs()));
    log.info("Target class : " + joinPoint.getTarget().getClass().getName());
    }

    @AfterReturning(pointcut = "loggingOperation()", returning = "result")
    @Order(2)
    public void logAfter(JoinPoint joinPoint, Object result)
    {
    log.info("Exiting from Method :" + joinPoint.getSignature().getName());
    log.info("Return value :" + result);
    }

    @AfterThrowing(pointcut = "execution(* com.abc.xyz.content.service..*(..))", throwing = "e")
    @Order(3)
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e)
    {
    log.error("An exception has been thrown in " + joinPoint.getSignature().getName() + "()");
    log.error("Cause :" + e.getCause());
    }

    @Around("execution(* com.abc.xyz.content.service..*(..))")
    @Order(4)
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable
    {
    log.info("The method " + joinPoint.getSignature().getName() + "() begins with " + Arrays.toString(joinPoint.getArgs()));
    try
    {
        Object result = joinPoint.proceed();
        log.info("The method " + joinPoint.getSignature().getName() + "() ends with " + result);
        return result;
    }
    catch (IllegalArgumentException e)
    {
        log.error("Illegal argument " + Arrays.toString(joinPoint.getArgs()) + " in " + joinPoint.getSignature().getName() + "()");
        throw e;
    }
    }

}

【问题讨论】:

    标签: java spring aop aspectj spring-aop


    【解决方案1】:

    其中一种选择怎么样?

    A) 带有包限制的一般执行切入点:

    execution(* *(..)) &&
    (
        within(com.abc.xyz..controller..*) ||
        within(com.abc.xyz..service..*) ||
        within(com.abc.xyz..dao..*)
    )
    

    B) 包限制的执行切入点:

    execution(* com.abc.xyz..controller..*(..)) ||
    execution(* com.abc.xyz..service..*(..)) ||
    execution(* com.abc.xyz..dao..*(..))
    

    顺便说一句,我更喜欢 B,只是因为它更短且更易于阅读。正如您可能已经猜到的那样,.. 表示法表示“任何包或子包”,而表达式末尾的 *.. 表示“任何类中的任何方法”。

    【讨论】:

    • 所以基本上可以使用其他切入点设计器定义所有within() 切入点表达式,对吧?我认为对于嵌套类,within() 可以简化表达式(有时非常),否则它只是一个方便的切入点指示符。
    • 理论上是的,但它通常是没有意义的。我总是会选择最清楚地表达我作为开发人员意图的切入点(组合)。好的切入点可以读成这样的句子:“在包 x 和 y 中,选择由 @Z 注释的类中的所有公共、非静态方法,但前提是它们返回类型 A 的值。”
    • 对我之前评论的后期修正:within 匹配的连接点类型不仅仅是execution,例如callgetsetinitializationstaticinitialization。它还匹配使用execution切入点时语法与方法执行不同的构造函数执行。
    【解决方案2】:

    您只需将切入点更改为以下内容:

    @Pointcut("within(com.abc.*)")
    

    进一步阅读 - https://docs.spring.io/spring/docs/2.0.x/reference/aop.html

    【讨论】:

    • 好的。对于控制器,您可以执行 stackoverflow.com/questions/2011089/… 之类的操作
    • 在名称为“dispatcher”的 DispatcherServlet 中找不到带有 URI [/xyz-web-vodafone/content.showContentWorkbench.htm] 的 HTTP 请求的映射
    • 首先我可以为服务和dao包配置它,你能告诉我如何实现吗
    • 它非常简单。您需要做的是在答案中提到的@Pointcut 本身内提供表达式。
    【解决方案3】:

    另一种选择是使用

    @Pointcut("bean(*Controller)")
    

    但是你的bean的命名应该是对应的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-25
      • 2011-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-19
      • 2019-12-31
      相关资源
      最近更新 更多