我试图在spring boot项目中使用spring aop。我不确定为什么我没有得到在主类的连接点编织的建议。 AOP在服务类中运行良好。代码如下。
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 在依赖项中包含 spring-boot-starter-aop 。
有人可以提出问题所在。
输出 -
hurray! In class: com.example.demo.services.SayHelloService - before method: message
Hello Dear User - George
答案 0 :(得分:3)
您需要在服务包之后使用两个点表示法(..
)来包含子包。开始使用* com.example.demo..*.*(..)
后,将记录除main
之外的所有Spring托管bean以及标记为@PostConstruct
的方法。根据{{3}},必须在类投入使用之前调用此方法。
@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());
}
}
如果将@Component
注释添加到Spring Boot主类并将其自动装配到另一个类,则将记录在SpringBootWithAOP
类中调用的任何方法。例如,
@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);
}
}
对SayHelloService
类的更改,
@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 ;
}
}
以下是已记录的消息
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
答案 1 :(得分:0)
“Spring AOP目前仅支持方法执行连接点(建议在 Spring beans 上执行方法)。”
我不相信应用程序Entrypoint是一个bean。
查看CommandLineRunner接口并实现自己的类覆盖run。命令行运行器将在bean初始化后立即运行。