【问题标题】:Is there a way of calling an advice method after execution of certain line of code using spring AOP有没有办法在使用spring AOP执行某些代码行后调用通知方法
【发布时间】:2020-07-02 10:48:55
【问题描述】:

我一直在使用 Aspect 来记录日志。现在我可以使用之前和之后的建议。但是是否可以在执行某些业务逻辑之后调用通知。这是我当前的代码,我想用建议替换我的代码。该怎么做?

@ComponentScan
@EnableCaching
@EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
public class Application {

    private final Logger log = LoggerFactory.getLogger(Application.class);

    @Inject
    private Environment env;

    @Inject
    private AppConfig appConfig;
    public void myBusinessLogicMethod(){
    if (myVariable == 0) {
                log.info("No Spring profile configured, running with default configuration");
                //rest of the business logic here
            } else {
                log.info("Running with number profile(s) : {}",myVariable);
    //           //rest of the business logic here
    
    }

我的方面类

@Aspect
@Order(0)
public class LoggingAspect {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Inject
    private HttpServletRequest request;

    @Inject
    private HttpServletResponse response;

    @Inject
    private Environment env;

    @Pointcut("(within(com.repository.*) || within(com.service.*) || "
            + "within(com.web.rest.*)) && "
            + "!@annotation(com.aop.logging.NoLogging)")
    public void loggingPoincut() {

    }

    @Before("within(com.web.rest.*) && "
            + "!@annotation(com.aop.logging.NoLogging)")
    public void beforeRest(JoinPoint point) throws UnknownHostException {
        String ipAddress = getIpAddress();
        if (log.isDebugEnabled()) {
            log.debug(">>>>>> From IP {}", isIpAvailble(ipAddress));
            log.debug("Enter: {}.{}() with argument[s] = {}", point.getSignature().getDeclaringTypeName(),
                    point.getSignature().getName(), Arrays.toString(point.getArgs()));
        }
    }

    @After("within(com.web.rest.*) && "
            + "!@annotation(com.aop.logging.NoLogging)")
    public void afterRest(JoinPoint point) throws UnknownHostException {
        if (log.isDebugEnabled()) {
            log.debug("Exit: {}.{}()", point.getSignature().getDeclaringTypeName(), point.getSignature()
                    .getName());
            log.debug("<<<<<< Rest Call Finished {} ", response.getStatus());
        }
    }
    
    }

如何在我的方面类中用建议替换紧密耦合的日志。

【问题讨论】:

  • 你使用的是 Spring AOP 还是 AspectJ?
  • @IgorKonoplyanko AspectJ。对不起,我会正确标记:)
  • 好吧,现在你标记了两者,所以更不清楚。为了帮助你,我需要看看你用cmets替换了什么。然后我可以建议如何重构现有代码以允许日志记录方面完成其工作。
  • @kriegaex 已更正,
  • 是的,但是我请求的附加代码在哪里?很遗憾,我无法读懂你的想法。

标签: java spring aspectj spring-aop


【解决方案1】:

简单的答案是:使用 Spring AOP,您可以拦截方法调用,而不是单行代码。即使可以,这也将是维护的噩梦,因为方法中的代码经常更改。即使您有一个稳定的公共方法 API,它们也是黑匣子,您(或您的一位同事)可以随时更改其内部实现。

但解决方案很简单:应用“清洁代码”原则(我希望您已经阅读过本书或了解其他来源的软件工艺运动),即使用简短的方法,将更复杂的代码分解成更小的、重新- 可用、命名良好且可维护的部分,复杂性低。将方法分解为日志记录所需的粒度级别,例如

public void myBusinessLogicMethod() {
  if (myVariable == 0)
    smallerBusinessLogicA(myVariable, someParameter);
  else
    smallerBusinessLogicB(myVariable);
}

然后使用您的日志切入点定位那些分解出来的方法,并记录它们的名称、参数和/或结果(无论您需要什么)。为了使它与 Spring AOP 一起工作,您需要小心

  • 要么将辅助方法分解到其他 Spring 组件类中,因为 Spring AOP 不支持自调用拦截
  • 或自注入 bean,以便您可以使用注入的 bean 调用辅助方法(即,您使用 AOP 代理,而不是对 AOP 一无所知的真正实现类)
  • 或从 Spring AOP 切换到不使用代理并使用自调用的完整 AspectJ。

Spring AOP 和 AspectJ 的另一个区别是前者只能针对非私有方法,而 AspectJ 则没有这样的限制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2022-11-07
    • 2018-12-01
    相关资源
    最近更新 更多