为什么Spring AOP使用CGLIB,尽管目标类实现了接口?

5m1hhzi4  于 2024-01-05  发布在  Spring
关注(0)|答案(1)|浏览(144)

Spring AOP是一个基于代理的AOP框架。这意味着要实现目标对象的方面,它将创建该对象的代理。这可以通过以下两种方式实现:

  • JDK动态代理-Spring AOP的首选方式。只要目标对象实现了一个接口,就会使用JDK动态代理
  • CGLIB代理-如果目标对象没有实现接口,则可以使用CGLIB代理


然而,总是使用CGLIB.这既适用于标准的Spring交付(例如,使用@ translation注解),也适用于其书面方面

  1. public interface MyService {
  2. void methodFirst();
  3. void methodSecond();
  4. }
  1. @Service
  2. public class MyServiceImpl implements MyService {
  3. @Override
  4. @AnnotationCustom
  5. public void methodFirst() {
  6. System.out.println("methodFirst()");
  7. methodSecond();
  8. }
  9. @Override
  10. @AnnotationCustom
  11. public void methodSecond() {
  12. System.out.println("methodSecond()");
  13. System.out.println();
  14. }
  1. @SpringBootApplication
  2. public class AopTransactionalSpringApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(AopTransactionalSpringApplication.class, args);
  5. }
  1. @Aspect
  2. @Component
  3. public class AspectCustom {
  4. @Pointcut("execution(public * *(..))")
  5. public void publicMethod() {}
  6. @Pointcut("@annotation(aop.transactional.spring.aop.annotation.AnnotationCustom)")
  7. public void annotatedMethodCustom() {}
  8. @Before("annotatedMethodCustom() && publicMethod()")
  9. public void printSomeMessage() {
  10. System.out.println(" AspectCustom");
  11. }
  12. }
  1. @SpringBootApplication
  2. public class AopTransactionalSpringApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(AopTransactionalSpringApplication.class, args);
  5. }
  • 测试
  1. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
  2. public abstract class AopTransactionalSpringApplicationTests {
  3. }
  1. class MyServiceTest extends AopTransactionalSpringApplicationTests {
  2. @Autowired
  3. private MyService myService;
  4. @Test
  5. void methodFirst() {
  6. myService.methodFirst();
  7. System.out.println();
  8. }
  9. }

的字符串

  • pom.xml
  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.5.0</version>
  5. <relativePath/> <!-- lookup parent from repository -->
  6. </parent>
  7. <properties>
  8. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  9. <java.source-target.version>11</java.source-target.version>
  10. </properties>
  11. <dependencies>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-data-rest</artifactId>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-starter-web</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-aop</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.postgresql</groupId>
  26. <artifactId>postgresql</artifactId>
  27. <scope>runtime</scope>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-test</artifactId>
  32. <scope>test</scope>
  33. </dependency>
  34. </dependencies>


文档中说如果我们使用接口,那么将使用JDK,如果目标类没有实现接口,那么将使用继承,然后CGLIB将创建一个代理,从目标类继承。但在调试模式下,我实际上观察到了其他东西。
为什么会这样?
也许我做错了什么,请指出我对这个问题理解上的错误。

epfja78i

epfja78i1#

根据官方Sping Boot 文档,进一步了解@m-deinum响应:

  • 默认情况下,Sping Boot 的auto-configuration会将Spring AOP配置为使用CGLib代理。要使用JDK代理,请将Spring prop:spring.aop.proxy-target-class设置为false。*

https://docs.spring.io/spring-boot/docs/3.2.0/reference/htmlsingle/#features.aop

相关问题