aspectj - AND和OR在同一个切入点中

时间:2018-04-17 11:19:54

标签: aop aspectj spring-aop aspect

我想在getAll(...)类中调用getRec(...)com.acme.dao.impl.*DaoImpl方法时执行某些操作但排除com.acme.dao.impl.*ViewDaoImpl类。

我可以用

完成第一项要求
execution(* com.acme.dao.impl.*DaoImpl.getAll(..)) || execution(* com.acme.dao.impl.*DaoImpl.getNRecs(..))

但不确定如何排除* ViewDaoImpl类 我认为我应该做像

这样的事情
!execution(* com.acme.dao.impl.*ViewDaoImpl.*(..))

但是如何添加到include表达式?

谢谢,

1 个答案:

答案 0 :(得分:3)

您有几种选择。最接近你已经拥有的那个是:

(execution(* com.acme.dao.impl.*DaoImpl.getAll(..)) || execution(* com.acme.dao.impl.*DaoImpl.getNRecs(..))) &&
!execution(* com.acme.dao.impl.*ViewDaoImpl.*(..))

但你也可以使用它,我认为它更具可读性:

within(com.acme.dao.impl.*DaoImpl) && !within(*..*ViewDaoImpl) &&
(execution(* getAll(..)) || execution(* getNRecs(..)))

假设所有DAO类都实现了与上面给出的相同的接口,这也可以工作(Dao+捕获所有实现类及其子类):

within(com.acme.dao.impl.Dao+) && !within(*..*ViewDaoImpl) &&
(execution(* getAll(..)) || execution(* getNRecs(..)))

这是一个纯粹的AspectJ示例,但它应该是Spring AOP的相同方面代码:

示例应用程序类:

package com.acme.dao.impl;

import java.util.List;

public interface Dao {
  List getAll();
  List getNRecs();
  void doSomething();
}
package com.acme.dao.impl;

import java.util.ArrayList;
import java.util.List;

public class FirstDaoImpl implements Dao {
  @Override
  public List getAll() {
    return new ArrayList();
  }

  @Override
  public List getNRecs() {
    return new ArrayList();
  }

  @Override
  public void doSomething() {}
}
package com.acme.dao.impl;

import java.util.ArrayList;
import java.util.List;

public class SecondDaoImpl implements Dao {
  @Override
  public List getAll() {
    return new ArrayList();
  }

  @Override
  public List getNRecs() {
    return new ArrayList();
  }

  @Override
  public void doSomething() {}
}
package com.acme.dao.impl;

import java.util.ArrayList;
import java.util.List;

public class MyViewDaoImpl implements Dao {
  @Override
  public List getAll() {
    return new ArrayList();
  }

  @Override
  public List getNRecs() {
    return new ArrayList();
  }

  @Override
  public void doSomething() {}
}

驱动程序应用程序:

package de.scrum_master.app;

import java.util.Arrays;

import com.acme.dao.impl.Dao;
import com.acme.dao.impl.FirstDaoImpl;
import com.acme.dao.impl.MyViewDaoImpl;
import com.acme.dao.impl.SecondDaoImpl;

public class Application {
  public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    for (Class<?> clazz : Arrays.asList(FirstDaoImpl.class, SecondDaoImpl.class, MyViewDaoImpl.class)) {
      Dao dao = (Dao) clazz.newInstance();
      dao.getAll();
      dao.getNRecs();
      dao.doSomething();
    }
  }
}

<强>方面:

我在切入点字符串中添加了很多换行符和缩进,当然你不需要这样做。在StackOverflow的Q / A场景中,这只是为了清楚起见。

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class DaoAspect {
  @Before(
    "(" + 
      "execution(* com.acme.dao.impl.*DaoImpl.getAll(..)) || " + 
      "execution(* com.acme.dao.impl.*DaoImpl.getNRecs(..))" + 
    ") && " + 
    "!execution(* com.acme.dao.impl.*ViewDaoImpl.*(..))"
  )
  public void firstVariant(JoinPoint thisJoinPoint) {
    System.out.println("[1] " + thisJoinPoint);
  }

  @Before(
    "within(com.acme.dao.impl.*DaoImpl) && " +
    "!within(*..*ViewDaoImpl) && " +
    "(" +
      "execution(* getAll(..)) || " +
      "execution(* getNRecs(..))" +
    ")" 
  )
  public void secondVariant(JoinPoint thisJoinPoint) {
    System.out.println("[2] " + thisJoinPoint);
  }

  @Before(
    "within(com.acme.dao.impl.Dao+) && " +
    "!within(*..*ViewDaoImpl) && " +
    "(" +
      "execution(* getAll(..)) || " +
      "execution(* getNRecs(..))" +
    ")" 
  )
  public void thirdVariant(JoinPoint thisJoinPoint) {
    System.out.println("[3] " + thisJoinPoint);
  }
}

控制台日志:

[1] execution(List com.acme.dao.impl.FirstDaoImpl.getAll())
[2] execution(List com.acme.dao.impl.FirstDaoImpl.getAll())
[3] execution(List com.acme.dao.impl.FirstDaoImpl.getAll())
[1] execution(List com.acme.dao.impl.FirstDaoImpl.getNRecs())
[2] execution(List com.acme.dao.impl.FirstDaoImpl.getNRecs())
[3] execution(List com.acme.dao.impl.FirstDaoImpl.getNRecs())
[1] execution(List com.acme.dao.impl.SecondDaoImpl.getAll())
[2] execution(List com.acme.dao.impl.SecondDaoImpl.getAll())
[3] execution(List com.acme.dao.impl.SecondDaoImpl.getAll())
[1] execution(List com.acme.dao.impl.SecondDaoImpl.getNRecs())
[2] execution(List com.acme.dao.impl.SecondDaoImpl.getNRecs())
[3] execution(List com.acme.dao.impl.SecondDaoImpl.getNRecs())

如您所见,所有三种变体都完全相同。根据您的喜好选择。