简体   繁体   中英

Spring + AspectJ pointcut on CrudRepository and Annotation

I have @Tenantable annotation to decide for pointCut :

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Tenantable {
}

this my aspect :

 @Slf4j
    @Aspect
    @Configuration
    public class TenancyAspect {

        @Pointcut("execution(public * *(..))")
        public void publicMethod() {}

        @Around("publicMethod() && @within(com.sam.example.aspect.aspectexample.model.Tenantable)")
        public Object tenatable(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("my operations ...");
            return joinPoint.proceed();
        }
    }

This is working without any problem for this service class :

@Tenantable
@Service
public class MyService(){
    public void doSomething(){
            ...
    }
}

my aspect is running when I call doSomething() method, It is ok but I want to implement aspect for CrudRepository interface that belongs spring data.

I have changed my Aspect to achieve this like below :

@Slf4j
@Aspect
@Configuration
public class TenancyAspect {

    @Pointcut("execution(public * *(..))")
    public void publicMethod() {}


    @Pointcut("this(org.springframework.data.repository.Repository)")
    public void repositoryExec(){}


    @Around("publicMethod() && repositoryExec() && @within(com.sam.example.aspect.aspectexample.model.Tenantable)")
    public Object tenatable(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("my operations ...");
        return joinPoint.proceed();
    }
}

this is repository :

@Tenantable
@Repository
public interface MyRepository extends CrudRepository{
}

But it doesn't work when I call any method inside of MyRepository.

Is there anyway to do this?

Edit : It works for all repositories when I apply these :

@Pointcut("execution(public * org.springframework.data.repository.Repository+.*(..))")

and exclude this :

@within(com.sam.example.aspect.aspectexample.model.Tenantable)

But I need this anotation to apply it for specific repositories.

Having taken another look, I think I know what is going on here: You are assuming that just because you made your annotation @Inherited , it will be inherited by implementing classes if you annotate an interface. But this assumption is wrong. @Inherited only works in exactly one case: when extending an annotated base class. It does not work for annotated interfaces, methods etc. This is also documented here :

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

As soon as you annotate your implementing class, it works.

您的repositoryExec切入点应以+结尾,以建议Repository所有子类

  @Pointcut("this(org.springframework.data.repository.Repository+)")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM