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

5m1hhzi4  于 5个月前  发布在  Spring
关注(0)|答案(1)|浏览(48)

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

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


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

public interface MyService {

    void methodFirst();

    void methodSecond();
}
@Service
public class MyServiceImpl implements MyService {

    @Override
    @AnnotationCustom
    public void methodFirst() {
        System.out.println("methodFirst()");
        methodSecond();
    }

    @Override
    @AnnotationCustom
    public void methodSecond() {
        System.out.println("methodSecond()");
        System.out.println();
    }
@SpringBootApplication
public class AopTransactionalSpringApplication {

    public static void main(String[] args) {
        SpringApplication.run(AopTransactionalSpringApplication.class, args);
    }
@Aspect
@Component
public class AspectCustom {

    @Pointcut("execution(public * *(..))")
    public void publicMethod() {}

    @Pointcut("@annotation(aop.transactional.spring.aop.annotation.AnnotationCustom)")
    public void annotatedMethodCustom() {}

    @Before("annotatedMethodCustom() && publicMethod()")
    public void printSomeMessage() {
        System.out.println(" AspectCustom");
    }
}
@SpringBootApplication
public class AopTransactionalSpringApplication {

    public static void main(String[] args) {
        SpringApplication.run(AopTransactionalSpringApplication.class, args);
    }
  • 测试
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public abstract class AopTransactionalSpringApplicationTests {
}
class MyServiceTest extends AopTransactionalSpringApplicationTests {

    @Autowired
    private MyService myService;

    @Test
    void methodFirst() {

        myService.methodFirst();
        System.out.println();
    }
}

的字符串

  • pom.xml
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.source-target.version>11</java.source-target.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </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

相关问题