1.说说我为什么开始放弃 Spring Framework
2.深入掌握Spring SpEL及其实战应用
3.头秃了,调试二十三张图带你从源码了解SpringBoot启动流程!源码g源
4.spring cloud zuul 原理简介及使用
5.SpringBoot读取.yml配置文件最常见的何调两种方式-源码及其在nacos的应用
说说我为什么开始放弃 Spring Framework
作为Java开发人员,Spring框架是调试我最常用的框架之一。Spring这个名字简洁而有寓意,源码g源它代表着程序员的何调nlms 算法 源码春天,同时Spring还象征着弹性,调试提供强大的源码g源扩展性。然而,何调在使用Spring的调试过程中,我逐渐开始质疑它的源码g源一些核心特性。
首先,何调Spring带来了强大的调试魔法,如自动注入(IoC)和面向切面编程(AOP),源码g源这些特性使得代码管理更加高效,何调增强了代码的可增强性。然而,动态技术也带来了新的挑战。Java本来是一个静态类型语言,拥有严格的类型约束,但Spring的动态技术打破了这种约束。SpEL(Spring Expression Language)是一个动态表达式语言,虽然提供了简洁的逻辑构建方式,但缺乏类型检查,这使得在IDE中没有足够的提示功能。这样的设计使得编写代码时存在潜在的危险,如变量名错误但程序仍能运行的情况,虽然参数拼接总是null,但导致了使用相同缓存数据。使用API形式可以避免此类问题,但便利性会有所下降。block puzzle 源码
其次,Spring的复杂度问题也不容忽视。Spring框架在设计时遵循面向接口和面向对象的原则,导致了继承和依赖关系的复杂性。复杂的代码结构和动态字节码技术的运用使得阅读源码变得困难,方法跳转和理解实现逻辑需要花费大量时间。虽然这对于解决复杂问题至关重要,但在遇到错误排查或调试代码时,这一复杂性会成为障碍。
随着生态的不断发展,Spring已成为一个庞大的框架,学习曲线陡峭,需要较高的成本才能熟练掌握。这种复杂性导致了所谓的“Spring八股文”现象,即大量的面试题和攻略在互联网上流行。中等规模的Spring Boot项目通常需要消耗1G的内存,而部署一个Spring Boot实例所消耗的内存,足以部署五六个vert.x实例。某些项目甚至需要长达1分半的启动时间,这导致了资源占用和性能问题。
Spring的不可靠性也逐渐显现。动态技术带来了一系列坑,如事务失效的种场景等。这些坑不仅增加了代码的复杂性,也使得问题难以察觉和解决。有些公司甚至禁止使用声明式事务,因为它们可能导致不明显的副作用,如缓存和校验失效。AOP技术的滥用也带来了不确定性,使得代码的网站源码扒皮执行路径难以追踪,增加了代码维护的难度。更糟糕的是,Spring Boot的自动配置可能存在安全风险,恶意代码可以通过自动配置在启动阶段执行。
经过深思熟虑,我发现Spring并不完美。动态字节码和代理技术虽然提供了灵活性,但也牺牲了静态语言的严谨性,使得编译期错误难以发现,只有运行时才能揭示问题。虽然IoC降低了耦合性,但我认为并非必须。在实际项目中,代码往往没有太多实现,不需要无缝替换或热插拔,而更高层次的抽象可能会导致失去部分原生特性的损失,甚至增加程序的复杂度。面向对象和面向接口的设计原则并不总是适用,有时过度设计反而会增加开发的复杂性。
基于以上考量,我决定不再局限于使用Spring框架。虽然Spring是一个有影响力的框架,但团队的一致性并非必须。探索其他解决方案对于我来说更具吸引力。在Java语言中,尽管存在不便之处,但动态字节码和代理技术并非解决所有问题的良药。了解其他语言并拓宽视野对于提升技术能力至关重要,这有助于打破固有思维模式,开阔开发者的althold源码分析思维格局。
深入掌握Spring SpEL及其实战应用
Spring Spring Expression Language(SpEL)是一种强大的表达式语言,支持运行时对象图的查询和操作。它类似于Unified EL,但增加了方法调用和基本字符串模板功能。SpEL是Spring家族产品中受支持的表达式语言,用于创建安全、灵活的应用。
在Spring Security中,四个关键注解用于安全控制:PreAuthorize、PostAuthorize、PreFilter、PostFilter。它们接收SpEL表达式。例如:
hasAuthority('ROLE_ADMIN') or #reqVo.sysUser.username == #userDetails.username
表示:当前登录用户必须拥有ROLE_ADMIN权限,或username匹配,才允许进入findUsers方法。
hasAuthority('ROLE_ADMIN') or (#reqVo.username == #userDetails.username and !T(org.springframework.util.StringUtils).isEmpty(#reqVo.password))
意味着:当前登录用户必须有ROLE_ADMIN权限,且username匹配且password非空,才允许进入updatePassword方法。
通过SpEL,可实现安全控制,其用途广泛,但应避免复杂安全表达式和嵌入无关业务逻辑,以免难以测试和调试。
SpEL可用于创建自定义功能,如接口加锁,避免重复用户名。通过注解和SpEL表达式,可实现此功能,且Spring Security注解处理也是淮北棋牌源码按此法实现。
SpEL具备多种强大功能,例如读取系统属性、解析基本类型数据、调用方法、解析对象属性值、调用Java类静态方法、注册方法和对象变量引用、处理null值和安全调用、进行List运算、访问map等。具体用法可参考官方文档。
项目源码可在GitHub和Gitee上找到,代码同步更新。
头秃了,二十三张图带你从源码了解SpringBoot启动流程!
源码版本
作者使用的是Spring Boot的2.4.0版本。不同版本的Spring Boot可能存在差异,建议读者与作者保持一致,以确保源码的一致性。
从哪入手
Spring Boot源码的研究起点是主启动类,即标注着`@SpringBootApplication`注解并且包含`main()`方法的类。这是Spring Boot启动的核心。
源码如何切分
SpringApplication中的静态`run()`方法是一个复杂的流程,它分为两步:创建`SpringApplication`对象和执行`run()`方法。接下来将分别介绍这两部分。
如何创建`SpringApplication`
创建`SpringApplication`的过程本质上是一个对象的生成,通过调试追踪,最终调用的构造方法如图所示。创建过程主要涉及三个阶段,我们将逐一进行深入。
设置应用类型
创建过程中的重要步骤是确定应用类型,这将直接影响项目的性质,如Web应用或非Web应用。应用类型由WebApplicationType枚举类决定,加载特定类(如DispatcherServlet)来判断。
设置初始化器
初始化器(ApplicationContextInitializer)用于在IOC容器刷新之前进行初始化操作,例如ServletContextApplicationContextInitializer。获取初始化器的方式是从SpringApplication中的方法调用开始的,最终通过`#SpringFactoriesLoader.loadSpringFactories()`方法从类路径加载。
设置监听器
监听器(ApplicationListener)负责监听特定的事件(如IOC容器刷新或关闭)。在Spring Boot中,使用SpringApplicationEvent事件来扩展监听器概念,主要在启动过程中触发。获取监听器的方式与初始化器相同,从spring.factories文件中加载。
总结
SpringApplication的构建为`run()`方法的执行铺平了道路,关键步骤包括设置应用类型、初始化器和监听器。注意,初始化器和监听器需要在spring.factories文件中声明,才能在构建过程中加载,此时IOC容器尚未创建,即使注入到容器中也不会生效。
执行`run()`方法
在构建结束后,到了启动的阶段,`run()`方法将执行一系列操作,分为八个步骤进行详细解析。
步骤1:获取并启动运行过程监听器
SpringApplicationRunListener监听器用于监听应用程序的启动过程,通过调用方法从spring.factories文件中获取运行监听器实例,并执行特定事件的广播。
步骤2:环境构建
构建过程包括加载系统和自定义配置(如application.properties),并广播事件通知监听器。
步骤3:创建IOC容器
执行容器创建过程,根据应用类型选择容器类型,此步骤仅创建容器,未进行其他操作。
步骤4:IOC容器的前置处理
这一步是容器刷新前的准备工作,关键操作是将主启动类注入容器,为后续自动化配置奠定基础。
步骤5:调用初始化器
执行构建过程中设置的初始化器,加载自定义的初始化器实现。
步骤6:加载启动类,注入容器
将主启动类加载到IOC容器中,作为自动配置的入口。
步骤7:两次事件广播
这一步涉及两次事件广播,包括ApplicationContextInitializedEvent和ApplicationPreparedEvent。
步骤8:刷新容器
容器刷新由Spring框架完成,包括资源初始化、上下文广播器等。
步骤9:IOC容器的后置处理
这一步是容器刷新后的扩展操作,通常用于打印结束日志等。
步骤:发出结束执行的事件
使用EventPublishingRunListener广播ApplicationStartedEvent事件,允许在IOC容器中注入的监听器响应。
步骤:执行Runners
Spring Boot提供了两种Runner,即CommandLineRunner和ApplicationRunner,用于定制额外操作。
总结
Spring Boot启动流程相对简洁,通过八个步骤详细描述了从创建到执行的整个过程。理解run()方法的执行流程、事件、初始化器和监听器的执行时间点是关键。
spring cloud zuul 原理简介及使用
Zuul是Netflix开源的一个API Gateway服务器,它本质上是一个Web Servlet应用,主要用于路由、过滤和增强微服务架构的API调用。
其工作原理主要包括过滤器机制。Zuul通过定义四种标准过滤器类型,如路由(ROUTE)、前置(PRE)、后置(POST)和错误(ERROR),来管理请求的生命周期。内置的过滤器如StaticResponseFilter和SurgicalDebugFilter提供了特殊的功能,如静态响应和调试日志。同时,用户还可以自定义过滤器来定制特定的行为,如直接生成响应,无需转发到后端服务。
Zuul的核心功能在于其动态过滤机制,通过在启动类上添加@EnableZuulProxy注解,能实现API网关的功能,如处理请求、路由规则配置、负载均衡、访问前缀设置等。例如,通过Eureka和Zuul的配合,可以自动配置路由,或者通过配置文件自定义路由规则。Ribbon和Hystrix的集成提供了内置的负载均衡和容错功能。
实战中,你可以引入相关依赖,配置application.yml,启用Zuul的网关功能。通过操作如添加自定义过滤器、配置访问路径前缀,以及使用Spring Boot Actuator查看路由信息,深入了解Zuul的工作方式。相关源码和详细教程可以在gitee和微信公众号等平台找到。
SpringBoot读取.yml配置文件最常见的两种方式-源码及其在nacos的应用
当开发过程中遇到需要动态管理的配置值,如数据库密码和关键链接,通常会借助配置文件如.yml进行管理。其中,SpringBoot提供了两种常见的配置文件读取方式。第一种是使用@Value注解直接引用配置,但不支持动态更新,而推荐的方式是@ConfigurationProperties(prefix = "school"),它不仅更规范,且配合Nacos可以实现动态修改,无需重启项目即可生效。第一种方式
最简单的@Value注解,直接在application.yml中定义键值对,无需额外复杂操作,如在Controller中直接使用即可。通过调试确认可以读取配置值。第二种方式(推荐)
推荐的方式更为全面,尤其在Nacos中,可以实时更新配置。首先,修改YML文件以支持更多元的数据类型。然后,定义一个读取映射的类,如Spring官方的ServerProperties,它通过@ConfigurationProperties来读取配置。在Controller中测试,无需重启项目,修改配置后即可立即生效。 在Nacos上直接配置YML,读取的配置与推荐的School类一致。通过Controller获取并使用Postman进行测试,修改配置后,不重启项目,再次测试,即可见到实时更新的效果。 总结起来,虽然第二种方式比第一种更繁琐,但其动态更新和与Spring官方推荐的兼容性使其在生产环境中更具优势。这是一篇关于SpringBoot读取.yml配置文件的实践指南,由博客园作者小王写博客分享,原文链接在此,详情请参阅原文。