I have one project using AOP - a sample program - which works. I created a project implementing AOP in (as far as I can see...) the same way which doesn't work.
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.11</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
AppConfig.java
@Configuration
@ComponentScan(basePackages = {
"com.phil.cardgame.aspects",
"com.phil.cardgame.service"
})
@EnableAspectJAutoProxy()
public class AppConfig {
}
EventAspect.java
@Aspect
@Component
public class EventAspect {
@Autowired
EventRepository eventRepository;
//@Around("execute(* com.phil.cardgame.service.GameService.createGame())")
//@Around("execute(* com.phil.cardgame.service.*.*(..))")
@Around("invalid text")
public long registerCreateGame(ProceedingJoinPoint joinPoint) throws Throwable{
String action = joinPoint.getSignature().toString();
long gameId = (long) joinPoint.proceed();
eventRepository.addEvent(action,gameId,null);
System.out.println(">>> got here");
return gameId;
}
In the EventAspect.java you can see the commented @Around advices I tried. The last one (invalid) produces no error. If I try the same in the working project I get an error: "Pointcut is not well-formed". So it looks like my EventAspect is not being inspected as an Aspect.
I've checked many other similar questions and I still can't see what I'm doing wrong - any ideas?
I cloned your project. Your aspect works. Despite being unrelated to your problem, just for fun let us
@Around
to @AfterReturning
, assuming, you only want to log successful calls; otherwise, you would use a mix of @Around
plus try-finally for the first advice and @After
for the others,package com.phil.cardgame.aspects;
import com.phil.cardgame.model.Deck;
import com.phil.cardgame.repository.EventRepository;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class EventAspect {
@Autowired
EventRepository eventRepository;
@Pointcut("within(com.phil.cardgame.service.GameService)")
public void inGameService() {}
@AfterReturning(value = "inGameService() && execution(* createGame())", returning = "gameId")
public void registerCreateGame(JoinPoint joinPoint, Long gameId) {
addEvent(joinPoint, gameId, null);
}
@AfterReturning("inGameService() && execution(* *(..)) && args(gameId, playerId)")
public void registerPlayerAction(JoinPoint joinPoint, long gameId, String playerId) {
addEvent(joinPoint, gameId, playerId);
}
@AfterReturning("inGameService() && execution(* *(..)) && args(gameId, deck)")
public void registerDeckAction(JoinPoint joinPoint, long gameId, Deck deck) {
addEvent(joinPoint, gameId, null);
}
@AfterReturning("inGameService() && execution(* *(..)) && args(gameId)")
public void registerGameAction(JoinPoint joinPoint, long gameId) {
addEvent(joinPoint, gameId, null);
}
private void addEvent(JoinPoint joinPoint, long gameId, String playerId) {
System.out.println(joinPoint);
eventRepository.addEvent(joinPoint.getSignature().toString(), gameId, playerId);
}
}
Now, change the main program like this:
package com.phil.cardgame;
import com.phil.cardgame.service.GameService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class CardgameApplication {
public static void main(String[] args) {
try (ConfigurableApplicationContext context = SpringApplication.run(CardgameApplication.class, args)) {
GameService gameService = context.getBean(GameService.class);
gameService.createGame();
gameService.addDeckToGame(1, gameService.createDeck());
gameService.addPlayerToGame(1, "jane");
gameService.findGame(1);
}
}
}
The console log will show:
execution(Long com.phil.cardgame.service.GameService.createGame())
execution(void com.phil.cardgame.service.GameService.addDeckToGame(long,Deck))
execution(Player com.phil.cardgame.service.GameService.addPlayerToGame(long,String))
execution(Game com.phil.cardgame.service.GameService.findGame(long))
To me, it looks like everything is working just fine.
Update: In Spring Boot, your invalid pointcut syntax for something like @Around(crepe)
is silently ignored, but if you wish to see the "Pointcut is not well-formed" log output, you can set
logging.level.org.springframework.aop=debug
in application.properties
. Then, on the console you will see something like (stripped off timestamp):
DEBUG 20508 --- [cardgame] [ main] o.s.a.aspectj.AspectJExpressionPointcut : Pointcut parser rejected expression [crepe]: java.lang.IllegalArgumentException: Pointcut is not well-formed: expecting '(' at character position 0
crepe
^