Issue
I'm using Spring AOP for exception handling but there is one point that I guess my component class is out of Spring Proxy so Spring AOP annotation that I created doesn't work in that class.
@Configuration
@AllArgsConstructor
public class MGRuleConfig {
private final GRepository repository;
private final GInitializer initializer;
private final GMapper mapper;
@Bean
@Qualifier("mRules")
public List<GRules> mRules(){
SSRule rule1 = new SSRule();
CSRule rule2 = new CSRule();
MPRule rule3 = new MPRule();
EGRule rule4 = new EGRule();
return List.of(rule1, rule2, rule3, rule4);
}
@Bean
public GService gService() {
return new MGServiceImpl(repository, initializer, mapper);
}
}
Then I have this service;
@Service
@RequiredArgsConstructor
public class MGServiceImpl implements GService {
............
@Override
public GaDTO executeRules(String gId, Integer pN) {
Ga ga = repository.findById(gId);
GaDTO gaDTO = mapper.toDTO(ga);
List<GaRules> mRules = (List<GaRules>) applicationContext.getBean("mRules");
mRules.forEach(rule -> rule.apply(gaDTO, pN));
repository.save(mapper.toEntity(gaDTO));
return gaDTO;
}
I need to put my exception handling annotation into that apply method but aspect doesn't work in that method.
@Component
public class SSRule implements GaRules {
@Override
@IPException
public void apply(GaDTO gaDTO, Integer pN) {
PDTO p1 = gaDTO.getP1();
PDTO p2 = gaDTO.getP2();
if (PTEnum.P_1.equals(gaDTO.getPT())) {
sS(gaDTO, pN, p1, p2);
} else {
sS(gaDTO, pN, p2, p1);
}
}
Annotation doesn't work in there. Here's my aspect class;
@Aspect
@Component
public class IPExceptionAspect {
@Around("execution(public * c.m.s.r.i.SSRule.apply(..)) && " +
"@annotation(c.m.s.i.a.IPException)")
public Object checkIP(ProceedingJoinPoint pjp) throws Throwable {
pjp.proceed();
return pjp;
}
}
So, what should I do to make IPException annotation and my Spring AOP work and why doesn't it work?
Solution
The problem is your code, you are creating instances of those rules yourself inside a bean method and expose them as a List
. Which means the bean is of type List
not your own SSRule
and thus it won't work.
Instead make an @Bean
method, or use the detected instance to inject into the list. As your SSRule
is annotated you will already have an instance, just inject that into your @Bean
method.
Bean
@Qualifier("mRules")
public List<GRules> mRules(SSRule rule1){
CSRule rule2 = new CSRule();
MPRule rule3 = new MPRule();
EGRule rule4 = new EGRule();
return List.of(rule1, rule2, rule3, rule4);
}
Now you will get the Spring managed instance which will have AOP applied.
Although I would hardly call this AOP as it is too specific for one class (not really crosscutting in that regard).
Answered By - M. Deinum