Reputation: 3690
I am trying to use spring aop in a spring boot project. I am not sure why I am not getting the advice weaved at the join point in main class. AOP is working well in a service class. The code is as below.
SpringBootWithAOP.java
package com.example.demo;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.example.demo.services.SayHelloService;
@SpringBootApplication
public class SpringBootWithAOP {
@Autowired
SayHelloService service;
String message;
static String name;
public static void main(String[] args) {
name="George";
SpringApplication.run(SpringBootWithAOP.class, args);
}
@PostConstruct
public void init() {
service.message(name);
}
}
SayHelloService.java
package com.example.demo.services;
import org.springframework.stereotype.Service;
@Service
public class SayHelloService {
public String message(String name) {
System.out.println("Hello Dear User - " + name );
return "Hello Dear User - " + name ;
}
}
MasterLoggerAspect.java
package com.example.demo.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MasterLoggerAspect {
@Before("execution(* com.example.demo.services.*.*(..) )")
public void doForEveryServicesMethod(JoinPoint jp){
System.out.println("hurray! In class: " + jp.getSignature().getDeclaringTypeName() + " - before method: " + jp.getSignature().getName());
}
//this advice is not getting weaved
@Before("execution(* com.example.demo.*.*(..)) " )
public void doForEveryMainClassMethod(JoinPoint jp){
System.out.println("hurray! In class: " + jp.getClass() + " - before method: " + jp.getSignature().getName());
}
}
pom.xml has spring-boot-starter-aop in the dependencies.
Could some one suggest where the problem exists.
Output -
hurray! In class: com.example.demo.services.SayHelloService - before method: message
Hello Dear User - George
Code available here: https://github.com/samshers/46692518/
Upvotes: 0
Views: 4535
Reputation: 7394
You need to use two dots notation (..
) after service package to include sub-packages. Once you start using * com.example.demo..*.*(..)
, all Spring managed beans will be logged except main
and the method tagged with @PostConstruct
. According to PostConstruct JavaDoc, this method MUST be invoked before the class is put into service.
@Component
@Aspect
public class MasterLoggerAspect {
@Pointcut("execution(* com.example.demo..*.*(..))")
public void logForAllMethods(){}
@Before("execution(* com.example.demo.services.*.*(..) )")
public void doForEveryServicesMethod(JoinPoint jp){
System.out.println("hurray! In class: " + jp.getSignature().getDeclaringTypeName() + " - before method: " + jp.getSignature().getName());
}
@Before("execution(* com.example.demo..*.*(..) )" )
public void doForEveryMainClassMethod(JoinPoint jp){
System.out.println("hurray! In class: " + jp.getClass() + " - before method: " + jp.getSignature().getName());
}
}
If you add @Component
annotation to the Spring Boot main class and autowire it to another class, then any method invoked in SpringBootWithAOP
class will be logged. For example,
@SpringBootApplication
@Component
public class SpringBootWithAOP {
@Autowired
SayHelloService service;
String message;
static String name;
public static void main(String[] args) {
name="George";
SpringApplication.run(SpringBootWithAOP.class, args);
}
public void sayHello() {
System.out.println("888888");
}
@PostConstruct
public void init() {
service.message(name);
}
}
Changes to SayHelloService
class,
@Service
public class SayHelloService {
@Autowired
SpringBootWithAOP aop;
public String message(String name) {
System.out.println("Hello Dear User - " + name );
aop.sayHello();
return "Hello Dear User - " + name ;
}
}
Here are the logged messages,
hurray! In class: class org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint - before method: message
hurray! In class: com.example.demo.services.SayHelloService - before method: message
Hello Dear User - George
hurray! In class: class org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint - before method: sayHello
888888
Upvotes: 3
Reputation: 187
"Spring AOP currently supports only method execution join points (advising the execution of methods on Spring beans)."
I do not believe the application Entrypoint is a bean.
Look at CommandLineRunner interface and implementing your own class that overrides run.The Command Line Runner will run as soon as the beans are initialized.
Upvotes: 0