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

您所在的位置:网站首页 springboot切面配置 SpringBoot默认开启AOP,采用Cglib代理方式?(Spring AOP快速入门)

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

#SpringBoot默认开启AOP,采用Cglib代理方式?(Spring AOP快速入门)| 来源: 网络整理| 查看: 265

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

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

@Configuration @ComponentScan("com.single") @EnableAspectJAutoProxy public class SpringConfig { }

        @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; }

②自定义aop注解

@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface AspectAnnotation { }

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

@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("后置增强"); } }

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

@Service public class TestService { public TestService() { System.out.println("TestService is created..."); } @AspectAnnotation public void test() { System.out.println("init......"); } }

⑤启动容器并调用方法

public class Application { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); TestService bean = ctx.getBean(TestService.class); bean.test(); } }

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

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

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

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

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

        然后再看下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 },

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

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

@ConditionalOnNean:当给定的bean存在时,则实例化当前Bean@ConditionalOnMissingBean:当给定的在bean不存在时,则实例化当前Bean,一般用户可覆盖的配置,例如很久之前的一篇关于RedisTemplate的帖子中提到的SpringBoot自动装配RedisTemplate,就用到了这个注解,当你自定义了RedisTemplate时,其本身的RedisTemplate就不会被注入,保证只有一个被注入@ConditionalOnWebApplication:当Spring为web服务时,才使注解的类生效;通常是配置类;@ConditionalOnResource:当指定的资源在类路径上时才会生效,例如@ConditionalOnResource(resources="classpath:jdbc.properties") 在这里插入图片描述 能力有限,不足之处请指正


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3