spring
Spring是Java编写的快速开发框架。集成大量三方包
Spring Framework Documentation :: Spring Framework
Spring Boot Reference Documentation
Spring示例:
https://github.com/xkcoding/spring-boot-demo.git
https://github.com/eugenp/tutorials.git
Quick Start
- 引入依赖,Maven 声明
- 声明主配置类 标识为 @SpringBootApplication,调用
SpringApplication#run(java.lang.Class<?>, java.lang.String...)静态方法创建实例,加载Spring功能 - 写 restful 接口;加外部化配置(可选,这是写业务逻辑的地方)
- 运行主配置类
Core
组件支持
Bean管理IOC
面向对象以对象为单位组织程序。创建对象这个操作不是业务功能,侵入业务,Spring 使用 Map 管理(创建、依赖管理、生命周期) 单例 Bean
涉及理念:
- Logic、Control、Data Structure 隔离:Logic 业务逻辑才是最有意义的部分,而 创建对象这种非业务功能 要从业务中脱离出来
- IOC:Inversion of Control控制反转。开发者不直接管理 Bean,交由底层框架 Spring 同一管理
- 单例:
- 单例对象为,应用运行的整个生命周期中,只被创建一次;区别于 每次使用都创建一次的多例
- Java中,开发者不直接管理 对象的创建和销毁(区别于C++),交由 JVM 统一管理,基于实践认为,频繁创建对象的成本高于内存存储,所有尽量使用单例对象。
Java中对象创建的方式
- new Class
- reflection,Spring 加载 Bean 使用此方式
Spring 可以管理的 Bean类型
- 单例Bean
- 内建Bean,可通过 getBean() 获取到
- 内建依赖
涉及的模块
- spring-boot:SpringApplication 含静态方法创建一个单例的 ApplicationContext(Bean 容器)
- 外部化spring.yml,可分 profile
- spring-boot-autoconfigure:根据 声明 加载 Bean,无配置加载默认 Bean。声明有:
- 本项目
- 主配置类 (含 main()的类、启动类):@ComponentScan 声明 bean 加载的 root 目录;默认是主配置类所在目录
- 1个类声明1个Bean:@Component ,Bean名 由 AnnotationBeanNameGenerator 实现,默认是 类名首字母小写; 1个类声明N个Bean:@Configuration+@Bean
- 参数配置:@ConfigurationProperties 声明配置前缀 / @Value 映射到字段
- 三方依赖 @SpringBootApplication
- 主配置类:@EnableAutoConfiguration
- 三方配置类声明 XXXAutoConfiguration, @Import 引入其他配置类,加入 spring.factories org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories
- 参数配置:application.yml ->对应配置类 XXXProperties
- 本项目
Bean 依赖 声明
@Resource
private 类B Bean名;
类循环依赖解决:属性注入可解决,引入中间存储 Map,利用类创建的时间差
Bean生命周期
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
- 销毁 Destruction
启动时的 Bean 扩展接口: 接口回调
- ApplicationRunner:启动后的操作,如 监听Redis队列,开启Socket 连接
- XXAware 获取Spring内部Bean
- XXConfiguration 配置类
- XXListener 监听器
- DisposableBean 接口或@PreDestroy : 关闭前的操作
1. 解析 Bean源
面向资源 {@link BeanDefinitionReader} / {@link BeanDefinitionParser} xml
2. 注册Bean {@link BeanDefinitionRegistry}
3. 类加载
{@link ClassLoader} / Java Security 安全控制 / ConfigurableBeanFactory
4. 实例化Bean Instantiation 构造器注入依赖
5. Aware接口回调阶段:开放 Spring中的资源
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware Bean工厂创建Bean
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware 获取资源加载器读取资源文件
ApplicationEventPublisherAware Bean可发布事件
MessageSourceAware
ApplicationContextAware 提供Bean
6. 初始化Bean Initialization BeanPostProcessor
Bean Map<属性,值> {@link PropertyValues}
{@link javax.annotation.PostConstruct} / {@link InitializingBean#afterPropertiesSet()} / {@link Bean#initMethod()}
7. 延迟初始化Bean Lazy Initialization
{@link Lazy}
8. 销毁Bean Destroy
{@link javax.annotation.PreDestroy} / {@link DisposableBean#destroy()} / {@link Bean#destroyMethod()}
9. Bean 垃圾回收(GC)
{@link AbstractApplicationContext#close()}
{@link org.springframework.context.ApplicationContext}
{@link CommandLineRunner} ???
ApplicationContext,功能
- 管理 Bean
- AOP
• 配置元信息(Configuration Metadata)
• 资源管理(Resources)
• 事件(Events)
• 国际化(i18n)
• 注解(Annotations)
• Environment 抽象(Environment Abstraction)
// Bean 存储 DefaultListableBeanFactory https://www.jianshu.com/p/ecd1cdd20e1b
// 缓存完全实例化的Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
存在问题
- 鼓励 状态 Bean,考虑并发安全
- 默认规约,封装了太多行为,不清晰
外部化配置
- 配置文件,application.yml ;compile / run 传递环境变量/命令行参数
- 配置类
- @Import( MyConfiguration.class ) / @Enable* 引入配置类,@Configuration 标注配置类 MyConfiguration,@ComponentScan/ 其作为Bean定义加载到Spring上下文
读取配置文件
org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource); //通过Properties加载资源
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryImplementationName = var9[var11];
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
方法扩展AOP
AOP,面向切面编程
解决OOP (Object Oriented Programming)静态化语言、侵入性扩展的局限,通过反射和代理模式实现
设计模式:代理模式、拦截器模式
原理
// 目标方法,期待被扩展的方法
public void bizMethod(){}
// AOP对 目标方法 进行扩展,使用动态代理:ClassLoader类加载时生成代理类字节码,运行时method.invoke()反射调用目标方法
// 字节码不一定要有文件,也可能是生成在内存中的字节数组
// 1. implements+ composition,要求必须有 interface; 新建类,与 目标方法 implements same interface
// ref: JDK 动态代理 Proxy.newProxyInstance(ClassLoader,Interface,InvocationHandler)
public void proxyMethod(){
log.info("请求目标方法前");
commonInterface.bizMethod();
log.info("请求目标方法后");
}
// 2. Inheritance
// Cglib 动态代理:Enhancer字节码增强器,创建代理类;MethodInterceptor 拦截目标方法
public void proxyMethod(){
log.info("请求目标方法前");
super.bizMethod();
log.info("请求目标方法后");
}
模块
- @Aspect 声明 切面类;@Order 声明切面优先级
- @Pointcut 声明 目标方法
- 拦截策略:全类名within/方法 execution;方法上的参数@args,注解@annotation,异常
- @Around ... 声明 方法的扩展方式,目标方法执行前后扩展
- JoinPoint 获取到目标方法
应用:事务,数据,缓存 /运行时日志,数据监控,安全防护
Spring 接口 - ResponseBodyAdvice
延伸
类扩展 编程范式
- 装饰器模式
通知Events
事件监听机制
ApplicationListener是Spring框架中的一个接口,用于监听应用程序中的事件并执行相应的逻辑。以下是几个ApplicationListener的主要实现类和它们所实现的功能:
ContextRefreshedEvent:当应用程序上下文被成功刷新(即完成初始化)时触发。在此事件中可以执行与应用程序初始化相关的后续逻辑。ContextStartedEvent:当应用程序上下文启动时触发。可以在此事件中执行与应用程序启动相关的额外逻辑。ContextStoppedEvent:当应用程序上下文停止时触发。可以在此事件中执行与应用程序停止相关的清理或处理逻辑。ContextClosedEvent:当应用程序上下文关闭时触发。可以在此事件中执行与应用程序关闭相关的资源释放或清理逻辑。ApplicationStartedEvent:当Spring应用程序开始启动时触发,早于上下文的创建。可以在此事件中执行与应用程序启动相关的逻辑。ApplicationEnvironmentPreparedEvent:在应用程序环境准备就绪之后、上下文创建之前触发。可以在此事件中执行与环境配置相关的逻辑。ApplicationFailedEvent:当应用程序启动失败时触发。可以在此事件中执行与应用程序错误处理相关的逻辑。
这些ApplicationListener的实现类可以通过注册到Spring应用程序上下文中,监听相应的事件并在事件发生时执行自定义的逻辑。通过实现不同的ApplicationListener接口并重写相应方法,开发人员可以针对不同的事件来处理特定的业务逻辑,扩展和定制应用程序的行为。
请注意,除了上述提及的几个常见实现外,还有其他ApplicationListener的子类和扩展,可以根据需求进行进一步的研究和使用。
// org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
// org.springframework.context.event.AbstractApplicationEventMulticaster
Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap(64);
private class ListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet();
}
## 表达式SpEL
String 类型的 SpEL,可以声明在注解上,做运行时计算,输出一个结果
字符串 -> 语法分析 -> 生成表达式对象 -> (添加执行上下文) -> 执行此表达式对象 -> 返回结果
- 表达式-干什么:SpEL的核心,所以表达式语言都是围绕表达式进行的
- 解析器-谁来干:用于将字符串表达式解析为表达式对象
- 上下文-在哪干:表达式对象执行的环境,该环境可能定义变量、定义自定义函数、提供类型转换等等
- root根对象及活动上下文对象-对谁干:root根对象是默认的活动上下文对象,活动上下文对象表示了当前表达式操作的对象
类型
Validation, Data Binding, Type Conversion、JSON
辅助支持
依赖配置starters
默认依赖配置
日志
- spring-boot:默认日志支持
- spring-boot-starter-web 引入 spring-boot-starter 引入 spring-boot-starter-logging
Web容器
内嵌Web容器,完全控制应用生命周期
- spring-boot:嵌入式Web 容器,可选 Tomcat、Jetty或Undertow
- spring-boot-starter-tomcat
loader
通过Maven 将应用打成Jar,可通过 java -jar 启动
资源环境配置
Resources, Environment
yml doc springboot
features.external-config
yml 占位符
spring:
web:
resources:
# 外部化配置优先于内部
static-locations: file:/static/,classpath:/static/
devtools
开发功能,自动重启,jar包会禁用此功能
actuator
Spring Boot Actuator Web API Documentation
执行器端点(HealthEndpoint、EnvironmentEndpoint、BeansEndpoint) 允许监控应用
WebMvcEndpointManagementContextConfiguration 加载
http://192.168.0.139:9326/actuator/health
Test
spring-boot-starter
spring-boot
spring-context:
spring-core:Cglib代理;
spring-boot-autoconfigure
spring-boot-starter-logging
+- org.springframework.boot:spring-boot-starter-web:jar:2.7.5:compile
| +- org.springframework.boot:spring-boot-starter:jar:2.7.5:compile
| | +- org.springframework.boot:spring-boot-starter-logging:jar:2.7.5:compile
| | \- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
| +- org.springframework.boot:spring-boot-starter-json:jar:2.7.5:compile
| | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.13.4:compile
| +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.7.5:compile
| +- org.springframework:spring-web:jar:5.3.23:compile
| \- org.springframework:spring-webmvc:jar:5.3.23:compile
spring-core:提供用于异常处理和版本检测的基本类,以及不特定于框架任何部分的其他核心助手。
支持注解
- 开启功能 @EnableXXX
功能支持
GitHub - spring-projects/spring-boot: Spring Boot
Data Access
spring-jdbc
spring-orm
spring-tx
spring-boot-starter-data-jdbc
druid-spring-boot-starter
Mybatis
DAO 支持(DAO Support)
O/R映射(O/R Mapping)
mybatis-plus-boot-starter
redisson-spring-boot-starter
事务抽象(Transactions)
mybatis
配置:分页
动态SQL
缓存
mybatis-plus
通用CRUD
条件构造器
代码生成
插件扩展
自定义全局操作
Redis
RedisTemplate
Redisson
数据类型,常用操作,主从搭建,哨兵集群,日志持久化
应用:数据共享,单点登录,计数器,限流,点赞,排行榜,分布式锁
雪崩,击穿,穿透,更新一致性
ref: database
Web
spring-web
@RestController=@Controller+@ResponseBody
- @Controller:handle incoming HTTP requests.
- @ResponseBody:方法的返回值直接以指定的格式写入Http response body中,而不是解析为要跳转的页面路径(Model)。格式的转换是通过HttpMessageConverter中的方法实现的,默认是JSON,字符编码 UTF-8;自定义序列化:
JsonSerializer和JsonDeserializer - @PathVariable:URL 上的值绑定到方法参数上
- @RequestParam:表单参数绑定到方法参数上
@RequestMapping:http-method mapping
web.servlet
此模块用于 映射(HTTP请求/响应,业务代码),并提供 线程池 和 校验支持
Web on Servlet Stack :: Spring Framework
WebMvcAutoConfiguration (Spring Boot 3.1.0 API) 配置类声明核心功能:
SpringBoot 处理请求流程
- tomcat,线程接受
- DispatcherServlet.doDispatch 分发
- HandlerMapping (Spring Framework 6.0.9 API) 映射到类/ HandlerAdapter (Spring Framework 6.0.9 API) 映射到方法
- HandlerExecutionChain#getHandler 处理
- HandlerInterceptor#prehandle 拦截;org.springframework.web.servlet.config.annotation.WebMvcConfigurer#addInterceptors 可以拦截请求(可匹配请求路径),添加前置操作 如 认证
- 默认的处理器 HandlerMethod 是 @Controller @RequestMapping @PathVariable
数据 HttpServletRequest (Jakarta EE Platform API)/ HttpServletResponse (Jakarta EE Platform API)
异常 HandlerExceptionResolver
org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error 异常处理接口
接口请求
字典
/dicts?dictType=xxx
/dicts
可以用同一个接口声明返回其值,不使用路径匹配注解(否则会报错:param not present)
@GetMapping("/dicts")
public List<DictDataVO> dicts(String dictType){
return dictDataService.getDictDataParamNullable(dictType);
}
接口命名规范:Java开发都需要参考的一份命名规范 - 知乎 (zhihu.com)
支持:
线程池:TaskExecution
校验:Validation:LocalValidatorFactoryBean.getValidator().validate
Validation
Java Bean Validation :: Spring Framework
LocalValidatorFactoryBean 可使用国际化 i18n messages.properties Common Application Properties (spring.io)
- 单字段校验
ConstraintValidator - 字段关联校验
DefaultGroupSequenceProvider - 字段关联比较
SpringSecurity
用户认证
权限管理
Shiro
Logging
XXL-JOB
drools 规则引擎
Filter, Listener,拦截器
spring-boot-starter-web
Spring MVC
WebSocket
Netty
IO模型,Channel,Buffer,Selector,Netty模型
WebSocket
Servlet
JSON
Jslt GitHub - schibsted/jslt: JSON query and transformation language
jsonSchema JSON Schema | The home of JSON Schema (json-schema.org)
模板引擎
Template Engines,数据与展示逻辑分离
远程调用(Remoting)
Messaging-统一消息服务
Kafka,RocketMQ
本地任务(Tasks)本地调度(Scheduling)-多线程+调度表达式
Control#定时调度
xxl-job-spring-boot-starter
缓存抽象(Caching)
Testing(Junit5)
Mock:对象生成不需要Web容器
Ng
正向代理,反向代理(负载均衡)
命令,配置,动静分离,集群搭建
MQ
RocketMQ, Kafka
生产消费模型,交换机模型,死信队列,延迟队列,消息持久化,Java操作,集群搭建
微服务
Dubbo:服务提供/消费
Spring Cloud:
服务注册发现,Consul
配置中心:Nacos
负载均衡
服务调用 Feign
服务限流,降级,熔断
服务容错
网关 Gateway
分布式服务总线
分布式链路追踪 Sleuth,SkyWalking
分布式
理论:CAP,BASE
一致性算法:Raft, Paxos, 一致性哈希
分布式事务:2PC,3PC,MQ事务消息,最大努力通知,LCN
ID:Leaf
服务调用:RPC
存储:HDFS
监控:Zabbix,Prometheus
Elastic
部署
Jenkins
Docker:容器,镜像,部署,Dockerfile, Compose, Macheine, Swarm, 多阶段构造
K8s:Ingress,资源类型,Pod(声明周期,安全策略),架构(组件,对象),工作负载,Kubectl,集群管理
messaging
Scheduling
Caching
工具包
EasyExcel
读Excel | Easy Excel (alibaba.com)
设计模式
API抽象
- JdbcTemplate
模块化设计
- AOP,SPEL,JCL-统一日志管理,Trasaction
- Core,Context,Beans
- instrument-字节码读入内存后,堆中生成Class对象前,修改字节码的特性。
- JDBC,ORM,OXM
- Test
功能稳定性
可扩展性
可测试性
编程模型
面向对象-契约接口
BeanDefinition:Bean抽象
面向切面-动态代理/字节码提升
面向元编程:注解,属性配置-占位符/外部化配置
面向模块编程:Maven,@Enable
面向函数编程:lambda,Reactive异步非阻塞
规约
面向对象
契约接口:Aware、BeanPostProcessor ...
设计模式:观察者模式、组合模式、模板模式 ...
对象继承:Abstract* 类
函数驱动
函数接口:ApplicationEventPublisher
Reactive:Spring WebFlux
面向切面
动态代理:JdkDynamicAopProxy
字节码提升:ASM、CGLib、AspectJ...
模块驱动
Maven Artifacts
Java 9 Automatic Modules
Spring @Enable* 模
面向元注解
注解:模式注解(@Component、@Service、@Respository ...)
配置:Environment 抽象、PropertySources、BeanDefinition ...
泛型:GenericTypeResolver、ResolvableType ...
模块设计
spring-framework/docs/5.3.25
- supports modules
- config(switch): ioc container, resources, aop, events, profile
- dependency injection
- foundationl:
- datas: transaction, JDBC, ORM, Dao(DATA Acces Object)
- web(mvc, json, data binding, type conversion validation, SpEL)
- utilities(Concurrency), messaging, Remoting, Tasks, Scheduling, Caching, log
- requires:JDK
spring-boot-2.7.8 feature
spring-context-5.3.25.jar
- cache
- context
- scheduling
- scripting