问题
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.
回答1:
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.
回答2:
Your repositoryExec pointcut should end with + to advice all subclass of Repository
@Pointcut("this(org.springframework.data.repository.Repository+)")
来源:https://stackoverflow.com/questions/51580725/spring-aspectj-pointcut-on-crudrepository-and-annotation