Java 业务开发常见错误 100 例
朱晔
贝壳金服资深架构师
52944 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 48 讲
代码篇 (23讲)
Java 业务开发常见错误 100 例
15
15
1.0x
00:00/00:00
登录|注册

20 | Spring框架:框架帮我们做了很多工作也带来了复杂度

解决问题的方法
Feign指定URL导致AOP失效
AOP切入Feign的实现
分享其他Spring框架的坑
利用PropertySources实现自动赋值
Spring AOP的其他指示器
配置源优先级的原因
ConfigurationPropertySourcesPropertySource的劫持
PropertySourcesPropertyResolver的查询过程
PropertySources的优先级
Property和Profile
用户名配置失效问题
环境变量覆盖配置文件配置
配置优先级
Feign AOP切不到的诡异案例
Spring Cloud和Spring Boot版本兼容性
Spring Boot自动配置
IoC和AOP配合使用
思考与讨论
Spring的Environment和PropertySources
Spring程序配置优先级问题
AOP切入问题
Spring框架复杂度
Spring框架复杂度与问题

该思维导图由 AI 生成,仅供参考

你好,我是朱晔。今天,我们聊聊 Spring 框架给业务代码带来的复杂度,以及与之相关的坑。
在上一讲,通过 AOP 实现统一的监控组件的案例,我们看到了 IoC 和 AOP 配合使用的威力:当对象由 Spring 容器管理成为 Bean 之后,我们不但可以通过容器管理配置 Bean 的属性,还可以方便地对感兴趣的方法做 AOP。
不过,前提是对象必须是 Bean。你可能会觉得这个结论很明显,也很容易理解啊。但就和上一讲提到的 Bean 默认是单例一样,理解起来简单,实践的时候却非常容易踩坑。其中原因,一方面是,理解 Spring 的体系结构和使用方式有一定曲线;另一方面是,Spring 多年发展堆积起来的内部结构非常复杂,这也是更重要的原因。
在我看来,Spring 框架内部的复杂度主要表现为三点:
第一,Spring 框架借助 IoC 和 AOP 的功能,实现了修改、拦截 Bean 的定义和实例的灵活性,因此真正执行的代码流程并不是串行的。
第二,Spring Boot 根据当前依赖情况实现了自动配置,虽然省去了手动配置的麻烦,但也因此多了一些黑盒、提升了复杂度。
第三,Spring Cloud 模块多版本也多,Spring Boot 1.x 和 2.x 的区别也很大。如果要对 Spring Cloud 或 Spring Boot 进行二次开发的话,考虑兼容性的成本会很高。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Spring框架的复杂性主要体现在IoC和AOP的灵活性、Spring Boot的自动配置以及Spring Cloud模块的多版本带来的挑战。本文通过两个案例展示了Spring框架的复杂性:一是配置AOP切入Spring Cloud Feign组件失败,二是Spring Boot程序的文件配置被覆盖。Spring框架借助IoC和AOP实现了修改、拦截Bean的定义和实例的灵活性,导致执行的代码流程不是串行的。Spring Boot的自动配置省去了手动配置的麻烦,但也增加了一些黑盒,提升了复杂度。另外,Spring Cloud模块多版本和Spring Boot 1.x和2.x的区别也增加了二次开发的兼容性成本。通过实际案例和代码分析,本文深入浅出地解释了Spring框架中配置优先级的问题,以及Spring环境中的配置源和查询过程。通过对Spring框架中的Property和Profile的抽象,以及对Environment接口的实现和配置源的分析,帮助读者更好地理解Spring框架中的配置优先级和查询过程。整体而言,本文通过深入的技术分析,帮助读者更好地理解Spring框架的复杂性和解决问题的方法。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 业务开发常见错误 100 例》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(12)

  • 最新
  • 精选
  • Darren
    置顶
    第一个问题: 切入点指示符 Spring AOP 支持10种切点指示符:execution、within、this、target、args、@target、@args、@within、@annotation、bean下面做下简记(没有写@Pointcut(),请注意): execution: 用来匹配执行方法的连接点的指示符。 用法相对复杂,格式如下:execution(权限访问符 返回值类型 方法所属的类名包路径.方法名(形参类型) 异常类型) e.g. execution(public String com.darren.hellxz.test.Test.access(String,String)) 权限修饰符和异常类型可省略,返回类型支持通配符,类名、方法名支持*通配,方法形参支持..通配 within: 用来限定连接点属于某个确定类型的类。 within(com.darren.hellxz.test.Test) within(com.darren.hellxz.test.) //包下类 within(com.darren.hellxz.test..) //包下及子包下 this和target: this用于没有实现接口的Cglib代理类型,target用于实现了接口的JDK代理目标类型 举例:this(com.darren.hellxz.test.Foo) //Foo没有实现接口,使用Cglib代理,用this 实现了个接口public class Foo implements Bar{...} target(com.darren.hellxz.test.Test) //Foo实现了接口的情况 args: 对连接点的参数类型进行限制,要求参数类型是指定类型的实例。 args(Long) @target: 用于匹配类头有指定注解的连接点 @target(org.springframework.stereotype.Repository) @args: 用来匹配连接点的参数的,@args指出连接点在运行时传过来的参数的类必须要有指定的注解 @Pointcut("@args(org.springframework.web.bind.annotation.RequestBody)") public void methodsAcceptingEntities() {} @within: 指定匹配必须包括某个注解的的类里的所有连接点 @within(org.springframework.stereotype.Repository) @annotation: 匹配那些有指定注解的连接点 @annotation(org.springframework.stereotype.Repository) bean: 用于匹配指定Bean实例内的连接点,传入bean的id或name,支持使用*通配符 切点表达式组合 使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系 第二个问题其实不太懂,网上搜了搜,核心应该是这个方法: org.springframework.util.PropertyPlaceholderHelper#replacePlaceholders(java.lang.String, java.util.Properties) 参考链接:https://www.jianshu.com/p/5fecf71024af

    作者回复: 第二个问题,我给了我的实现:https://github.com/JosephZhu1983/java-common-mistakes/tree/master/src/main/java/org/geekbang/time/commonmistakes/springpart2/custompropertysource

    2020-04-28
    2
    33
  • hellojd
    我也经常看框架源码,但缺失了老师的演示及溯源过程,学习到了。

    作者回复: :)

    2020-04-28
    8
  • 梦倚栏杆
    1. 配置优先级的问题,理解热加载的时候仔细的看过,知道有这么回事,老师举得这个例子:开发和运维都设置了配置,然后运维的把开发的覆盖了,这种问题如果遇到了怎么查呢?如果是同一个人统一管理还好说,不同的人谁知道谁设置了什么呢? 2. 切面不成功的内容,我卡在了切面上。切面怎么用还不太了解。

    作者回复: 可以参考我文中的例子,程序启动的时候检查一下所有配置项,发现有重复配置的话发出告警

    2020-04-28
    6
  • 招财
    老师,我现在项目中遇到了一个问题,就是用springboot的全局异常处理时,响应出去的信息,编码格式都是ISO-8859-1,试过了在配置文件中设置spring.http.encoding.charset=utf-8和过滤器中给response去setCharacterEncoding为utf-8,但是还是不行。正常响应的数据是不乱码的,只有全局异常处理出去的响应有乱码,这个应该怎么解决呀

    作者回复: spring.http.encoding.charset=UTF-8 spring.http.encoding.force=true spring.http.encoding.enabled=true 试过吗?

    2020-05-21
    3
    1
  • 旅途
    老师 问两个问题 1.第一个例子 去掉ribbon依赖后 ApacheHttpClient注册了bean 所以@FeignClient这里面直接就使用的ApacheHttpClient的bea 不走那个new 的代码了是吗 ? 2.第二个例子. ConfigurationPropertySourcesPropertySourcess这个类实际上一个代理 查询的走的还是其他的配置源 这么做的意义是什么?

    作者回复: 1. 去掉ribbon依赖后,ApacheHttpClient的注册方式就正确了,成为了一个Bean,而不是LoadBalancerFeignClient的delegate 2、Spring这么干是为了实现relaxed binding,参考 https://spring.io/blog/2018/03/28/property-binding-in-spring-boot-2-0

    2020-05-03
    1
  • jacy
    有个疑问,思考与讨论二中的真实数据库密码放哪呢?

    作者回复: 密码可以由DBA统一管控,由DBA提供一个接口给到框架在运行时查询数据库对应的密码

    2021-05-10
  • 龙猫
    这节课有点难度啊
    2020-06-07
    11
  • 汝林外史
    感觉就在等最后的解决方案,然后戛然而止了。。。
    2020-04-29
    11
  • 程序员小跃
    源码之下无秘密,但是看源码挑战了一个程序员的心境,需要耐心,细心,恒心,给自己加油
    2020-07-23
    3
  • Geek_8b92bf
    within(feign.Client+) 为什么是切入execute方法,不是切人api方法,这个不太明白
    2022-06-24
    1
收起评论
显示
设置
留言
12
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部