【问题标题】:AspectJ matching Annotated classes but not its child classesAspectJ 匹配带注释的类但不匹配其子类
【发布时间】:2014-07-23 04:34:53
【问题描述】:

我想在我的 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 来执行我的设计规则。当我使用以下错误和切入点声明时,(合法)UserDao 中的代码也会出现错误,因为它继承了 AbstractDao 的注释。

@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)?

【问题讨论】:

    标签: java annotations aop aspectj


    【解决方案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 语法,我觉得这更直观。

    【讨论】:

    • 这是我的第一个想法,所有 DAO 类都匹配事务类,因为它们继承自具有 @Transactional 注释的 AbstractDao,而不仅仅是那些具有显式注释的类。
    • 我不关注你。尽管 transactionaClass 匹配所有 DAO 对象,但最终切入点受到限制,因此只考虑 DAO 的子类。但无论如何,我更喜欢下面的第二个答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多