AspectJ匹配带注释的类,但不匹配其子类

时间:2014-07-21 13:52:03

标签: java annotations aop aspectj

我想在我的DAO父类上配置事务,并禁止具体的DAO有自己的事务配置,所以我使用Springs @Transactional

@Transactional(/* some transactionConfig */)
abstract class AbstractDao
{
    //...
}

// this is ok
class UserDao extends AbstractDao
{
    //...
}

@Transactional (/* some other config*/) // this should be illegal
class DocumentDao extends AbstractDao
{
    //...
}

我使用AspectJs @DeclareError来强制执行我的设计规则。当我使用followint错误和切入点声明时,我在(合法)UserDao中的代码上也会收到错误,因为它从AbstractDao继承了Annotation。

@Pointcut("call(*.new(..)) || call(* *(..)) || set (* *) || get (* *)")
public void doAnything()
{
    // no code
}

@Pointcut("within(@org.springframework.transaction.annotation.Transactional *) && doAnything()")
public void transactionalClass()
{
    // only pointcut, no code
}

@Pointcut("within(AbstractDao+) && !within(AbstractDao)")
public void inDao()
{
    // no code
}

@DeclareError("transactionalMethod() && doAnything() && inDao()")
public static final String TRANSACTIONAL_NOT_ALLOWED =
        "@Transactional of this method is not necesarry, we have it on class level in AbstractDao";

@DeclareError("transactionalClass() && inDao() && doAnything()")
public static final String ERROR = "Transactional is not allowed on method level";

是否可以只匹配明确注释的类(在本例中为DocumentDao)?

1 个答案:

答案 0 :(得分:-1)

因此,我认为您希望在AbstractDao的子类中捕获@Transactional对方法或类的使用。假设是这种情况,以下情况应该有效:

@Pointcut("within(AbstractDao+) && !within(AbstractDao)")
public void inDao()
{
    // no code
}

@Pointcut("within(@org.springframework.transaction.annotation.Transactional *)")
public void transactionalClass()
{
    // no code
}

@Pointcut("withinCode(@org.springframework.transaction.annotation.Transactional *.*(..))")
public void transactionalMethod()
{
    // no code
}

@DeclareError("(transactionalMethod() || transactionalClass()) && inDao()")
public static final String TRANSACTIONAL_NOT_ALLOWED = "NOT ALLOWED!";

我实际上没有尝试过这个,所以你可能需要对切入点进行一些调整,但这是应该有用的。


编辑:这是一个更简洁的答案:

pointcut transactionsNotAllowed() : (within(@Transactional AbstractDao+) || 
  execution(@Transactional * AbstractDao+.*(..))) && !within(AbstractDao);

这对你有用。它使用代码风格的aspectj语法,我发现它更加直观。