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

sky*_*yho 5 java spring spring-aop spring-boot java-11

\n

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

\n
    \n
  • JDK动态代理\xe2\x80\x93是Spring AOP的首选方式。每当目标对象实现一个接口时,就会使用 JDK 动态代理
  • \n
  • CGLIB代理\xe2\x80\x93 如果目标对象没有实现接口,则可以使用CGLIB代理
  • \n
\n
\n

来源

\n

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

\n
public interface MyService {\n\n    void methodFirst();\n\n    void methodSecond();\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n
@Service\npublic class MyServiceImpl implements MyService {\n\n    @Override\n    @AnnotationCustom\n    public void methodFirst() {\n        System.out.println("methodFirst()");\n        methodSecond();\n    }\n\n    @Override\n    @AnnotationCustom\n    public void methodSecond() {\n        System.out.println("methodSecond()");\n        System.out.println();\n    }\n\n
Run Code Online (Sandbox Code Playgroud)\n
@SpringBootApplication\npublic class AopTransactionalSpringApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(AopTransactionalSpringApplication.class, args);\n    }\n
Run Code Online (Sandbox Code Playgroud)\n
@Aspect\n@Component\npublic class AspectCustom {\n\n    @Pointcut("execution(public * *(..))")\n    public void publicMethod() {}\n\n    @Pointcut("@annotation(aop.transactional.spring.aop.annotation.AnnotationCustom)")\n    public void annotatedMethodCustom() {}\n\n    @Before("annotatedMethodCustom() && publicMethod()")\n    public void printSomeMessage() {\n        System.out.println(" AspectCustom");\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
@SpringBootApplication\npublic class AopTransactionalSpringApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(AopTransactionalSpringApplication.class, args);\n    }\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 测试
  • \n
\n
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\npublic abstract class AopTransactionalSpringApplicationTests {\n}\n
Run Code Online (Sandbox Code Playgroud)\n
class MyServiceTest extends AopTransactionalSpringApplicationTests {\n\n    @Autowired\n    private MyService myService;\n\n    @Test\n    void methodFirst() {\n\n        myService.methodFirst();\n        System.out.println();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • pom.xml
  • \n
\n
\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.0</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.source-target.version>11</java.source-target.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-rest</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aop</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.postgresql</groupId>\n            <artifactId>postgresql</artifactId>\n            <scope>runtime</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n
Run Code Online (Sandbox Code Playgroud)\n

文档说,如果我们使用接口,那么将使用JDK,如果目标类没有实现该接口,则将使用继承,然后CGLIB将创建一个代理,从目标类继承。但在调试模式下,我实际上观察到了其他东西。

\n

这是为什么?

\n

也许我做错了什么,请指出我对这个问题的理解错误。

\n

小智 0

根据 @m-deinum 的回应,根据 Spring boot 官方文档:

\n

默认情况下,Spring Boot\xe2\x80\x99s 自动配置将 Spring AOP 配置为使用 CGLib 代理。要使用 JDK 代理,请将 configprop:spring.aop.proxy-target-class 设置为 false。

\n

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

\n