• SpringBoot默认开启AOP,采用Cglib代理方式?(Spring AOP快速入门)


    1. Spring中的AOP需要手动开启

            在Spring中,如果我们采用注解的方式进行AOP,则需要手动开启SpringAOP支持,如下例子:
    ① 定义Spring的配置类,主要声明需要扫描的包路径,并且打开AOP功能

    @Configuration
    @ComponentScan("com.single")
    @EnableAspectJAutoProxy
    public class SpringConfig {
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

            @EnableAspectJAutoProxy该注解即为打开AOP的注解,我们也可以通过该注解选择动态代理的方式,默认情况下,Spring采用JDK的动态代理,我们可以点进该注解看下,请重点看下第一个属性的注释

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
    	/**
    	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
    	 * to standard Java interface-based proxies. The default is {@code false}.
    	 *  翻译过来就是:指示是否创建基于子类(CGLIB)的代理,而不是标准的基于Java接口的代理。默认值为{@code false}
    	 *  说白了就是默认是false,采用JDK,如果你想用Cglib,那你就设置为true
    	 */
    	boolean proxyTargetClass() default false;
    	
    	boolean exposeProxy() default false;
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ②自定义aop注解

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface AspectAnnotation {
    }
    
    • 1
    • 2
    • 3
    • 4

    ③编写切面类、切点、以及增强

    @Component
    @Aspect
    public class AspectTest {
        @Pointcut("@annotation(com.single.annotation.AspectAnnotation)")
        public void pointCut() {}
        
        @Before("pointCut()")
        public void before(JoinPoint point) {
            System.out.println("前置增强");
        }
        
        @After("pointCut()")
        public void after() {
            System.out.println("后置增强");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ④在需要被增强的方法上添加自定义注解,方法所在bean一定要交给Spring管理

    @Service
    public class TestService {
    
        public TestService() {
            System.out.println("TestService is created...");
        }
    
        @AspectAnnotation
        public void test() {
            System.out.println("init......");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    ⑤启动容器并调用方法

    public class Application {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
            TestService bean = ctx.getBean(TestService.class);
            bean.test();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ⑥结果
    在这里插入图片描述

    2. SpringBoot中的AOP默认开启,并采用Cglib代理方式

            在SpringBoot中,AOP的使用与上述没有区别,只不过不需要我们手动开启AOP功能了,主要是因为SpringBoot的自动装配,如果你读过SpringBoot的源码,相比你一定会知道在spring-boot-autoconfigureMETA-INF下有一个spring.factories文件,它里面指明了很多需要自动装配的配置类的路径,在启动的时候会自动将这些配置类中定义的bean装配到IOC中,原理不多说了,感兴趣的可以去研究一下。
            我们来看一下这个文件
    在这里插入图片描述

            可以看到自动配置中有一个AOP的配置类,找到它,源码如下:
    在这里插入图片描述
            可以看到第53行和61行都用了@EnableAspectJAutoProxy注解,但是这个配置生效的前提条件是由@ConditionalOnProperty注解来控制的,通过@ConditionalOnProperty控制配置类是否生效,可以将配置与代码进行分离,实现了更好的控制配置。例如上图54行:

    @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class",
     havingValue = "false", matchIfMissing = false)
    
    • 1
    • 2

            然后再看下META-INF下的配置文件spring-configuration-metadata.json

        {
          "name": "spring.aop.proxy-target-class",
          "type": "java.lang.Boolean",
          "description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
          "defaultValue": true
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

            配置文件代码为defaultValue=true@ConditionalOnProperty 实现是通过 havingValue 与配置文件中的值对比,返回为true则配置类生效,反之失效。由此可知,SpringBootAOP默认采用的是Cglib代理方式。其实此处还是涉及到了SpringBoot自动装配的原理了,而且还是按需加载的,感兴趣的朋友可以研究一下

    拓展:@ConditionalOnXXX,该注解实际上是类加载的一种先决条件,加载当前Bean必须先存在给定条件,还有 @ConditionalOnMissingXXX,即加载当前Bean必须先不存在给定条件,例如

    1. @ConditionalOnNean:当给定的bean存在时,则实例化当前Bean
    2. @ConditionalOnMissingBean:当给定的在bean不存在时,则实例化当前Bean
    3. @ConditionalOnWebApplication:当Spring为web服务时,才使注解的类生效;通常是配置类;
    4. @ConditionalOnResource:当指定的资源在类路径上时才会生效,例如@ConditionalOnResource(resources="classpath:jdbc.properties")
      在这里插入图片描述
      能力有限,不足之处请指正
  • 相关阅读:
    Android moveTaskToBack方法测试
    OBS Studio免费开源录屏工具
    以数据为中心 的AI v.s. 以模型为中心的AI
    苹果宣布9月26日发布全新macOS Sonoma系统 新增不少实用功能
    串口收发UART(Verilog HDL)
    高通平台稳定性分析-CFI failure
    WebAPI项目搭建及其发布测试
    计算机是如何工作的(上篇)
    React 函数组件导出自定义方法的办法说明
    SpringMVC ---- @RequestMapping注解
  • 原文地址:https://blog.csdn.net/qq_41563912/article/details/125896748