「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」前端
Springboot
中 AOP
失效的缘由今天 4ye 来和小伙伴们分享一个小实战啦 ,冲冲冲~ (。・∀・)ノjava
(我竟然拖到如今才写了这文章…… 😵)git
主要是在一个周日(2020.6.6)在技术群里看到一个老哥在问github
“怎么用切面来捕获自定义异常?” ( ̄▽ ̄)"web
我当时想的是,捕获异常不是很常见的吗,平时常常用到这个全局异常捕获 ,因而就把本身 GitHub
上的小例子发给他(主要是这个 ControllerAdvice
注解),如图 👇spring
结果老哥过了一段时候就加了我,还问我有没有空帮忙看下,还想打电话问我,我当时的心里是后端
这么急的吗(瑟瑟发抖……)springboot
不过恰好在外面没时间,就婉拒了,后来晚上回来,愣是花了两个钟,才看懂 为啥这个AOP
没有生效?为啥没能捕获到异常?markdown
下面进入主题👉(项目总体介绍)maven
在该项目中,maven项目采用多模块构建,父子结构,由 父maven 来统一管理这些公共包,以及项目的总体版本属性配置等
里面有两个模块,starter
模块和 core
模块,其中 starter
模块依赖 core
模块,总体以下图👇
不知道小伙伴们看到上面的 starter
有没有嗅到什么 ?
一开始我觉得是常见的 自定义starter ,可是里面的内容却和我想的有点出入,竟然只有一个 spring.factories
文件, 很明显这里使用到了 Springboot 的 SPI 机制。
这个在咱们以前的 👉 Springboot自动装配原理探索 一文中有介绍到,小伙伴们能够前去了解看看~😄
对两个模块中的核心部分进行展开,结构以下👇
core项目描述:非web项目里面只有 service
,没有启动类等
👉 因为 core 模块 不是web项目!!,因此这个 ControllerAdvice
是确定不能用的,毕竟它是在 web
包中的,通常咱们在 web项目中配合这个@ExceptionHandler(Exception.class)
实现全局异常捕获,而后进行统一处理的。
👉 从 Springboot 的 SPI 机制 中咱们能够得知,Springboot
项目启动时,会去扫描各个项目中的 META-INF/spring.factories
文件(包括各个jar包),而后将其中的配置信息读取到内存中,而自动配置时会根据必定的条件对这些类进行筛选,最后建立符合的类,完成这个自动装配。
很明显,这里就是经过自动配置,来实现相关 bean
的注入。
那么,在了解了这些基本信息后,咱们能够把目光移到这个 xxxConfig
上,这里模仿了一个👇
紧接着就是项目中的切面配置了,例如之前写的小例子:👇
代码在个人 GitHub
:
经过异常通知来捕获
除了上面这两个以外,项目中没有用到其余配置了!
这个时候问题就来了,在定义了切面以后,发现根本没有在项目中起做用!而其余均可以正常运行!
因而我一直在想,这是为啥呀,明明切面已经定义好了呀……
终于,我开始了尝试,在 yaml
配置文件中添加这个参数
spring:
aop:
auto: true
复制代码
由于在印象中,这个默认是 true
,会默认使用这个 @EnableAspectJAutoProxy
, 不用咱们手动去添加这个 @EnableAspectJAutoProxy
注解(以前一直没有手动添加这个注解)🐖
结果也没什么效果……
因而乎,我决定手动添加到刚刚那个 xxxConfig
配置类上,结果也没有什么做用……
终于,我才想起那个 切面配置 没有被加载到这个 Spring
中 ,因而我又在那个配置类 xxxConfig
上添加了这个包扫描注解 @ComponentScan(basePackages = "com.xxx.xxx")
结果终于成功了!
因而我赶在 23:59 将修改后的文件发给那位老哥后,却发现他竟然睡着了 哈哈哈
解决问题后,咱们能够发现这个问题就下面两点👇
SpringIOC
容器中@EnableAspectJAutoProxy
第一步的解决也很简单,就是没有配置这个包扫描 @ComponentScan(basePackages = "com.xxx.xxx")
第二步的解决嘛,就有点一头雾水了当时,毕竟以前也不须要我手动去添加的,并且从配置的描述信息中能够发现,即便咱们没有配置,他也是默认开启的,会自动使用这个注解的~
那么小伙伴们知道第二步问题的所在吗😄
嘿嘿,答案就出在这个自动配置 身上,能够发现咱们上面都没有使用到这个 @EnableAutoConfiguration
注解,而在咱们的 SpringBootApplication
组合注解中,最重要的就是它了! 经过它去开启了咱们的这个自动装配。
这个时候又得把这文章搬出来了 👉 Springboot自动装配原理探索 哈哈
那么咱们再来看看这个 AOP自动装配的配置类
AopAutoConfiguration
源码以下👇
开头有这么一个条件注解
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
复制代码
havingValue = "true"
的意思是:值为 true
时才有效
matchIfMissing = true
的意思是:没有配置这个属性时也能加载
接着让咱们把目光移到第一个静态内部类: AspectJAutoProxyingConfiguration
如图👉:
这个咱们也比较熟悉啦, proxyTargetClass
为 true
时表示使用 cglib
,false
使用 JDK
动态代理
接着看最后的静态内部类: ClassProxyingConfiguration
能够发现它这里的条件是和 AspectJAutoProxyingConfiguration
相反的,当没有这个 Advice
类时,帮咱们去注册这个代理到 IOC
中
看完该AOP自动装配类后, 咱们能够发现当咱们使用 @EnableAutoConfiguration
自动装配注解时并引入 AOP
的包时,它会自动帮咱们装配这个AopAutoConfiguration
,而它里面就使用到了 @EnableAspectJAutoProxy
,因此咱们通常不用手动添加该注解。
嘿嘿,再出一个小问题考考小伙伴😝
有没有细心的小伙伴发现上面的 core
模块是没有用到这个 SpringBootApplication
的,并且咱们也没有用到这个 @EnableAutoConfiguration
,那么没有自动装配,这个 SPI
显然也没啥做用 ,那么,咱们在项目中要怎么测试呢~
答案就在 单元测试的注解身上 @SpringBootTest(classes = xxxConfiguration.class)
经过这个 classes
,咱们直接指定并实例化这个配置类就能够了
我也是报错了才知道 哈哈😝
嘿嘿,老规矩,画个图总结下啦👇
那么,本期就分享到这啦,喜欢的小伙伴记得点点赞呀~ 下期看看状况分享下下面某一个叭😝
欢迎小伙伴们来一块儿探讨问题~
若是你以为本篇文章还不错的话,那拜托再点点赞支持一下呀😝
让咱们开始这一场意外的相遇吧!~
欢迎留言!谢谢支持!ヾ(≧▽≦*)o 冲冲冲!!
我是4ye 我们下期应该……很快再见!! 😆