【Spring Boot 源码学习】OnWebApplicationCondition 详解
Spring Boot 源码学习系列
OnWebApplicationCondition 详解
- 引言
- 往期内容
- 主要内容
- 1. getOutcomes 方法
- 2. getMatchOutcome 方法
- 3. isWebApplication 方法
- 3.1 isServletWebApplication 方法
- 3.2 isReactiveWebApplication 方法
- 3.3 isAnyWebApplication 方法
- 总结
引言
上篇博文带大家从 Spring Boot
源码深入详解了 OnBeanCondition,那本篇也同样从源码入手,带大家深入了解 OnWebApplicationCondition 的过滤匹配实现。
往期内容
在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:
Spring Boot 源码学习 |
Spring Boot 项目介绍 |
Spring Boot 核心运行原理介绍 |
【Spring Boot 源码学习】@EnableAutoConfiguration 注解 |
【Spring Boot 源码学习】@SpringBootApplication 注解 |
【Spring Boot 源码学习】走近 AutoConfigurationImportSelector |
【Spring Boot 源码学习】自动装配流程源码解析(上) |
【Spring Boot 源码学习】自动装配流程源码解析(下) |
【Spring Boot 源码学习】深入 FilteringSpringBootCondition |
【Spring Boot 源码学习】OnClassCondition 详解 |
【Spring Boot 源码学习】OnBeanCondition 详解 |
主要内容
本篇我们重点详解 OnWebApplicationCondition
的实现,参见如下:
1. getOutcomes 方法
鉴于前面博文的了解,我们知道 OnWebApplicationCondition
也是 FilteringSpringBootCondition
的子类,所以这里同样也是从 getOutcomes
方法源码来分析【Spring Boot 2.7.9】:
@Order(Ordered.HIGHEST_PRECEDENCE + 20)
class OnWebApplicationCondition extends FilteringSpringBootCondition {// ...@Overrideprotected ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,AutoConfigurationMetadata autoConfigurationMetadata) {ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];for (int i = 0; i < outcomes.length; i++) {String autoConfigurationClass = autoConfigurationClasses[i];if (autoConfigurationClass != null) {outcomes[i] = getOutcome(autoConfigurationMetadata.get(autoConfigurationClass, "ConditionalOnWebApplication"));}}return outcomes;}// ...
}
上述逻辑很容易理解,遍历自动配置数组 autoConfigurationClasses
,循环如下:
-
首先,从
autoConfigurationClasses
中获取自动配置数据autoConfigurationClass
; -
然后,调用
AutoConfigurationMetadata
接口的get(String className, String key)
方法来获取与autoConfigurationClass
关联的名为"ConditionalOnWebApplication"
的条件属性值【即应用类型枚举值】;应用类型枚举可以查看
@ConditionalOnWebApplication
注解获取,如下所示: -
最后,调用
getOutcome
方法,并传入上述获取的应用类型枚举值type
:
- 如果
type
是SERVLET
, 则判断org.springframework.web.context.support.GenericWebApplicationContext
是否存在;
如果不存在,则返回一个未满足过滤匹配条件的ConditionOutcome
对象【其中包含 did not find servlet web application classes 的信息 】。 - 如果
type
是REACTIVE
,则判断org.springframework.web.reactive.HandlerResult
是否存在;
如果不存在,则返回一个未满足过滤匹配条件的ConditionOutcome
对象【其中包含 did not find reactive web application classes 的信息 】。 - 如果
org.springframework.web.context.support.GenericWebApplicationContext
不存在且org.springframework.web.reactive.HandlerResult
也不存在,则返回一个未满足过滤匹配条件的ConditionOutcome
对象【其中包含 did not find reactive or servlet web application classes 的信息 】。 - 如果都存在,则直接返回
null
。
- 如果
2. getMatchOutcome 方法
同 OnClassCondition
一样,OnWebApplicationCondition
同样实现了 FilteringSpringBootCondition
的父类 SpringBootCondition
中的抽象方法 getMatchOutcome
方法。
有关
SpringBootCondition
的介绍,这里不赘述了,请查看笔者的 【Spring Boot 源码学习】OnClassCondition 详解。
那么,我们进入 getMatchOutcome
方法中查看如下源码【Spring Boot 2.7.9】:
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {boolean required = metadata.isAnnotated(ConditionalOnWebApplication.class.getName());ConditionOutcome outcome = isWebApplication(context, metadata, required);if (required && !outcome.isMatch()) {return ConditionOutcome.noMatch(outcome.getConditionMessage());}if (!required && outcome.isMatch()) {return ConditionOutcome.noMatch(outcome.getConditionMessage());}return ConditionOutcome.match(outcome.getConditionMessage());
}
我们来分析一下相关逻辑:
-
首先,通过调用
AnnotatedTypeMetadata
接口的isAnnotated
方法,判断元数据中是否存在@ConditionalOnWebApplication
注解【当应用程序为 Web 应用程序时,该条件注解用来匹配】。如果返回true
,表示元数据中存在指定注解;否则,返回false
。 -
然后,调用
isWebApplication
方法来获取条件匹配结果outcome
【有关内容查看 第 3 小节】; -
如果
required
为true
【即存在@ConditionalOnWebApplication
注解】,并且 条件结果不匹配,则返回一个新的ConditionOutcome
对象,标记为不匹配,并带有原始的消息。 -
如果
required
为false
【即不存在@ConditionalOnWebApplication
注解】,并且 条件结果匹配,则同样返回一个新的ConditionOutcome
对象,标记为不匹配,并带有原始的消息。 -
最后,上述两个条件判断都不满足,则将返回一个匹配的
ConditionOutcome
对象,并带有原始的消息。
3. isWebApplication 方法
下面,我们进入 isWebApplication
方法中:
private ConditionOutcome isWebApplication(ConditionContext context, AnnotatedTypeMetadata metadata,boolean required) {switch (deduceType(metadata)) {case SERVLET:return isServletWebApplication(context);case REACTIVE:return isReactiveWebApplication(context);default:return isAnyWebApplication(context, required);}
}
上述的逻辑也很简单:
-
首先,通过
deduceType
方法获取可获取的应用类型;查看其源码可知,如果存在@ConditionalOnWebApplication
注解,则获取其对应的type
属性;否则默认返回Type.ANY
【即任何Web
应用程序都将匹配】。private Type deduceType(AnnotatedTypeMetadata metadata) {Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnWebApplication.class.getName());if (attributes != null) {return (Type) attributes.get("type");}return Type.ANY; }
-
如果是
Type.SERVLET
,则调用isServletWebApplication
方法返回条件匹配结果。 -
如果是
Type.REACTIVE
,则调用isReactiveWebApplication
方法返回条件匹配结果。 -
如果不是上述两个应用类型,则默认调用
isAnyWebApplication
方法返回条件匹配结果。
3.1 isServletWebApplication 方法
我们直接翻看 isServletWebApplication
方法的源码,如下:
private ConditionOutcome isServletWebApplication(ConditionContext context) {ConditionMessage.Builder message = ConditionMessage.forCondition("");if (!ClassNameFilter.isPresent(SERVLET_WEB_APPLICATION_CLASS, context.getClassLoader())) {return ConditionOutcome.noMatch(message.didNotFind("servlet web application classes").atAll());}if (context.getBeanFactory() != null) {String[] scopes = context.getBeanFactory().getRegisteredScopeNames();if (ObjectUtils.containsElement(scopes, "session")) {return ConditionOutcome.match(message.foundExactly("'session' scope"));}}if (context.getEnvironment() instanceof ConfigurableWebEnvironment) {return ConditionOutcome.match(message.foundExactly("ConfigurableWebEnvironment"));}if (context.getResourceLoader() instanceof WebApplicationContext) {return ConditionOutcome.match(message.foundExactly("WebApplicationContext"));}return ConditionOutcome.noMatch(message.because("not a servlet web application"));
}
我们来详细分析一下:
- 首先,检查类加载器中是否存在
org.springframework.web.context.support.GenericWebApplicationContext
?- 如果没有,那么将返回不匹配的结果,并附带消息
"did not find servlet web application classes"
。
- 如果没有,那么将返回不匹配的结果,并附带消息
- 如果条件上下文
context
中BeanFactory
不为空,则获取所有注册的scope
名称,并检查其中是否包含"session"
。如果包含,则返回匹配的结果,并附带消息"found session scope"
。 - 如果条件上下文
context
中Environment
是ConfigurableWebEnvironment
的实例,则将返回匹配的结果,并附带消息"found ConfigurableWebEnvironment"
。 - 如果条件上下文
context
中ResourceLoader
是WebApplicationContext
的实例,那么将返回匹配的结果,并附带消息"found WebApplicationContext"
。 - 如果上述的条件都不满足,则最后将返回不匹配的结果,并附带消息
"not a servlet web application"
。
3.2 isReactiveWebApplication 方法
同样,我们也先来查看下 isReactiveWebApplication
方法的源码,如下:
private ConditionOutcome isReactiveWebApplication(ConditionContext context) {ConditionMessage.Builder message = ConditionMessage.forCondition("");if (!ClassNameFilter.isPresent(REACTIVE_WEB_APPLICATION_CLASS, context.getClassLoader())) {return ConditionOutcome.noMatch(message.didNotFind("reactive web application classes").atAll());}if (context.getEnvironment() instanceof ConfigurableReactiveWebEnvironment) {return ConditionOutcome.match(message.foundExactly("ConfigurableReactiveWebEnvironment"));}if (context.getResourceLoader() instanceof ReactiveWebApplicationContext) {return ConditionOutcome.match(message.foundExactly("ReactiveWebApplicationContext"));}return ConditionOutcome.noMatch(message.because("not a reactive web application"));
}
通过上述 isServletWebApplication
方法中的分析,我们可以很快总结下:
- 首先,检查类加载器中是否存在
org.springframework.web.reactive.HandlerResult
?- 如果没有,那么将返回不匹配的结果,并附带消息
"did not find reactive web application classes"
。
- 如果没有,那么将返回不匹配的结果,并附带消息
- 如果条件上下文
context
中Environment
是ConfigurableReactiveWebEnvironment
的实例,则将返回匹配的结果,并附带消息"found ConfigurableReactiveWebEnvironment"
。 - 如果条件上下文
context
中ResourceLoader
是ReactiveWebApplicationContext
的实例,那么将返回匹配的结果,并附带消息"found ReactiveWebApplicationContext"
。 - 如果上述的条件都不满足,则最后将返回不匹配的结果,并附带消息
"not a reactive web application"
。
3.3 isAnyWebApplication 方法
还是一样,我们先来看看 isAnyWebApplication
方法的源码,如下:
private ConditionOutcome isAnyWebApplication(ConditionContext context, boolean required) {ConditionMessage.Builder message = ConditionMessage.forCondition(ConditionalOnWebApplication.class,required ? "(required)" : "");ConditionOutcome servletOutcome = isServletWebApplication(context);if (servletOutcome.isMatch() && required) {return new ConditionOutcome(servletOutcome.isMatch(), message.because(servletOutcome.getMessage()));}ConditionOutcome reactiveOutcome = isReactiveWebApplication(context);if (reactiveOutcome.isMatch() && required) {return new ConditionOutcome(reactiveOutcome.isMatch(), message.because(reactiveOutcome.getMessage()));}return new ConditionOutcome(servletOutcome.isMatch() || reactiveOutcome.isMatch(),message.because(servletOutcome.getMessage()).append("and").append(reactiveOutcome.getMessage()));
}
这里就更简单了,总结如下:
- 首先,通过调用 isServletWebApplication 方法获取条件匹配结果;
- 如果
Servlet Web
应用程序的条件结果匹配并且required
为true
,则返回一个包含匹配状态和相关消息的ConditionOutcome
对象。
- 如果
- 接着,通过调用 isReactiveWebApplication 方法获取条件匹配结果;
- 如果
Reactive Web
应用程序的条件结果匹配并且required
为true
,则同样返回一个包含匹配状态和相关消息的ConditionOutcome
对象。
- 如果
- 最后,如果上述两种情况都不满足 或者
required
为false
,则返回一个新的ConditionOutcome
对象,它包含servletOutcome.isMatch() || reactiveOutcome.isMatch()
的匹配状态 和servletOutcome
与reactiveOutcome
两者拼接的消息。
总结
本篇 Huazie 带大家从源码角度深入了解了自动配置过滤匹配子类 OnWebApplicationCondition
,至此 Spring Boot 中有关自动配置过滤匹配的三个实现已经介绍完毕,当然有关过滤匹配条件的内容还没结束,下一篇笔者将介绍 @Conditional
条件注解。
相关文章:
【Spring Boot 源码学习】OnWebApplicationCondition 详解
Spring Boot 源码学习系列 OnWebApplicationCondition 详解 引言往期内容主要内容1. getOutcomes 方法2. getMatchOutcome 方法3. isWebApplication 方法3.1 isServletWebApplication 方法3.2 isReactiveWebApplication 方法3.3 isAnyWebApplication 方法 总结 引言 上篇博文带…...
力扣之二分法
今天,学习了二分法,详细内容见代码随想录 (programmercarl.com),讲得十分好。 力扣之35. 搜索插入位置 - 力扣(LeetCode)。 class Solution { public:int searchInsert(vector<int>& nums, int target) {in…...
css图形化理解--扭曲函数skew()
transform: skewX(30deg);transform: skewY(45deg);transform: skew(30deg,45deg);transform: skewX(angleX);transform: skewY(angleY);transform: skew(angleX,angleY); 是CSS中的一个2D变换方法,它用于对元素沿X轴、Y轴进行倾斜变换。其中,angle表示倾…...
八、互联网技术——物联网
文章目录 一、智慧物联案例分析二、M2M技术三、数据保护综合案例分析一、智慧物联案例分析 智能物流是一种典型的物联网应用。一个物流仓储管理系统架构如下图所示: [问题1] 图中的三层功能:仓库物品识别、网络接入、物流管理中心,分别可对应到物联网基本架构中的哪一层? …...
聊聊MySQL的聚簇索引和非聚簇索引
文章目录 1. 索引的分类1. 存储结构维度2. 功能维度3. 列数维度4. 存储方式维度5. 更新方式维度 2. 聚簇索引2.1 什么是聚簇索引2.2 聚簇索引的工作原理 3. 非聚簇索引(MySQL官方文档称为Secondary Indexes)3.1 什么是非聚簇索引3.2 非聚簇索引的工作原理…...
python之subprocess模块详解
介绍 subprocess是Python 2.4中新增的一个模块,它允许你生成新的进程,连接到它们的 input/output/error 管道,并获取它们的返回(状态)码。 这个模块的目的在于替换几个旧的模块和方法。 那么我们到底该用哪个模块、哪个…...
第10讲:Vue组件的定义与注册
定义组件 1. 在程序的 components 目录下新建一个名为 Child.vue 的文件 2. 在文件内键入如下代码 <template><div>Child</div> </template> <script> export default {name: Child } </script>新建的 Child .vue 文件即为我们定义的组件…...
Pycharm操作git仓库 合并等
菜单 Git CommitPushUpdate ProjectPullFetchMergreRebase 查询 查询分支 查询本地所有分支 # 查询本地分支 git branch# 查询远程分支 git branch -rPycharm查看当前分支 步骤: Git->Branches 哈喽,大家好,我是[有勇气的牛排]&…...
Flink+Doris 实时数仓
Flink+Doris 实时数仓 Doris基本原理 Doris基本架构非常简单,只有FE(Frontend)、BE(Backend)两种角色,不依赖任何外部组件,对部署和运维非常友好。架构图如下 可以 看到Doris 的数仓架构十分简洁,不依赖 Hadoop 生态组件,构建及运维成本较低。 FE(Frontend)以 Java 语…...
windows 任务计划自动提交 笔记到github 、gitee
一、必须有个git仓库托管到git上。 这个就不用说了,自己在github或者码云上新建一个仓库就行了。 二、创建自动提交脚本 这个bat脚本是在windows环境下使用的。 注意:windows定时任务下 调用自动提交git前,必须先进入该git仓库目录&#x…...
闭包和装饰器
#闭包的作用 #全局变量有被修改的风险,代码在命名空间上不够干净整洁 #第一种,不使用闭包的场景 account_amount0 def atm(num,depositTrue):global account_amountif deposit:account_amountnumprint(f"存款:{num},账户余额…...
注册器模式
注册器模式 注册器模式(Registry Pattern)是一种设计模式,用于管理和维护对象的注册和检索。它允许您在运行时注册对象,并通过一个唯一的标识符或名称来检索这些对象。这种模式通常用于构建可扩展的、松耦合的系统,其…...
5SpringMVC处理Ajax请求携带的JSON格式(“key“:value)的请求参数
SpringMVC处理Ajax 参考文章数据交换的常见格式,如JSON格式和XML格式 请求参数的携带方式 浏览器发送到服务器的请求参数有namevalue&...(键值对)和{key:value,...}(json对象)两种格式 URL请求会将请求参数以键值对的格式拼接到请求地址后面,form表单的GET和POST请求会…...
学习笔记|ADC|NTC原理|测温程序|STC32G单片机视频开发教程(冲哥)|第十九集:ADC应用之NTC
文章目录 1.NTC的原理开发板上的NTC 2.NTC的测温程序编写3.实战小练总结课后练习 1.NTC的原理 NTC(Negative Temperature Coefficient)是指随温度上升电阻呈指数关系减小、具有负温度系数的热敏电阻现象和材料。该材料是利用锰、铜、硅、钴、铁、镍、锌…...
Redisson 集成SpringBoot 详解
一、引入依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.5</version></dependency> redison-spring-boot-starter依赖于与最新版本的spring-boot兼容…...
C# 下载模板文件 Excel
后端代码 [HttpGet("DownloadExcel")]public async Task<dynamic> DownloadExcel(string tmplName){var _fileName "导入表模板.xlsx";var filePath "Files\DownLoad\";var NewFile Path.Combine(filePath, tmplName);var stream new…...
如何做好sop流程图?sop流程图用什么软件做?
5.如何做好sop流程图?sop流程图用什么软件做? 建立标准作业程序sop已经成为企业进步和发展的必经之路,不过,很多刚刚开始着手搭建sop的企业并不知道要如何操作,对于如何做sop流程图、用什么软件做sop流程图等问题充满…...
JAVA编程题-求矩阵螺旋值
螺旋类 package entity; /*** 打印数组螺旋值类*/ public class Spiral { // 数组行private int row; // 数组列private int col; // 行列数private int size; // 当前行索引private int rowIndex; // 当前列索引private int colIndex; // 行开始索引private int rowStart; //…...
Python--入门
标识符 标识符由字母,数字,下划线_组成 第一个字符不能是数字,必须是字母或下划线 标识符区分大小写 关键字 关键字即保留字,定义标识符时不能使用关键字,python中的关键字如下图 注释 python中的单行注释用 # 多行注…...
STM32复习笔记(二):GPIO
目录 (一)Demo流程 (二)工程配置 (三)代码部分 (四)外部中断(EXTI) (一)Demo流程 首先,板子上有4个按键,…...
POJ 3264 Balanced Lineup 线段树 / 平方分割
一、题目大意 给出一个长度为 n(n<50000) 数组 arr,进行Q次查询(Q<200000),每次查询的内容为数组arr在 [L , R] 的切片的极差(最大元素 - 最小元素) 二、解题思路 1、线段树 区间极差…...
element-plus自动引入组件报错,例如collapse、loading
element-plus自动引入组件,例如collapse、loading,使用时报错,报错信息如下图所示: 解决办法:vite-config.ts改变vue的引入顺序,将vue放在第一个...
ChainForge:衡量Prompt性能和模型稳健性的GUI工具包
ChainForge是一个用于构建评估逻辑来衡量模型选择,提示模板和执行生成过程的GUI工具包。ChainForge可以安装在本地,也可以从chrome浏览器运行。 ChainForge可以通过聊天节点对多个对话可以使用不同的llm并行运行。可以对聊天消息进行模板化,并…...
队列--二叉树层序遍历
/*1/ \2 3/\ /\4 5 6 7利用LinkedListQueue1. 头 [1] 尾12.头 [2 3] 尾1 23.头 [3 4 5] 尾1 24.头 [4 5 6 7] 尾1 2 35.头 [] 尾1 2 3 4 5 6 7*/ 代码: class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List&l…...
Ceph入门到精通-Linux内核网络参数优化小结
tcp建连优化 1 tcp建连,降低客户端超时时间 net.ipv4.tcp_syn_retries 6 2 tcp建连,服务端避免syn攻击 netstat -s | grep "SYNs to LISTEN" 1192450 SYNs to LISTEN sockets dropped 可以考虑增大syn队列 net.ipv4.tcp_max_syn_backlo…...
AWK语言第二版 2.6个人库 2.7小结
2.6 个人库 Awk提供了适量的内置函数库,如 length、sub、substr、printf 等其他十来个;在A.2.1节的参考手册中都有列出。你可以自己创建更多函数,以便有需要时引入到Awk程序中。比如内置库函数 sub 和 gsub 都只能返回替换的次数,…...
8年经验之谈 —— Web ui自动化测试框架总结!
实施过了web系统的UI自动化,回顾梳理下,想到什么写什么,随时补充。 首先,自动化测试不是手动测试的替代品,是比较好的补充,而且不是占大比重的补充。 70%的测试工作集中在底层接口测试和单元测试࿰…...
Kafka在企业级应用中的实践
前言 前面说了很多Kafka的性能优点,有些童鞋要说了,这Kafka在企业开发或者企业级应用中要怎么用呢?今天咱们就来简单探究一下。 1、 使用 Kafka 进行消息的异步处理 Kafka 提供了一个可靠的消息传递机制,使得企业能够将不同组件…...
使用企业订货系统后的效果|软件定制开发|APP小程序搭建
使用企业订货系统后的效果|软件定制开发|APP小程序搭建 企业订货系统是一种高效的采购管理系统,它可以帮助企业更好地管理采购流程,降低采购成本,提高采购效率。 可以帮助企业提高销售效率和降低成本的软件工具。使用该系统后,企业…...
STL关联式容器set,multiset,pair,map
set容器是一个集合容器。包含元素是唯一的。集合元素按照一点顺序排列,元素插入过程是顺序插入,所有不能插入指定位置。 set采用红黑树变体的数据结构实现。红黑树属于平衡二叉树。再插入和删除上比vector快。 set不能直接存取元素(不能用a…...
建设企业网站的目的/线上推广的渠道有哪些
点击下面链接,来测测您的javaScript水平吧。 JavaScript Puzzlers! 21. function f() {} var a f.prototype, b Object.getPrototypeOf(f); a b; //false f.prototype输出Object {constructor: function},是f的实例对象的原型(实例对象就是…...
js 网站简体繁体/今日头条搜索优化
选自过去1~2周的内容: https://twitter.com/unity3d “UGUIEffect”可以用uGUI实现在波浪上反射的阴影 https://github.com/AsehesL/UGUIEffect Unity 2019.1.0a10新功能现在可以通过单击Console的调用堆栈跳转到源代码的函数调用行 从Unity 2019.1.0a10开始 &a…...
河南郑州百度网站建设/seo网站优化方案书
简单的说,Python是一个“优雅”、“明确”、“简单”的编程语言。 学习曲线低,非专业人士也能上手开源系统,拥有强大的生态圈解释型语言,完美的平台可移植性支持面向对象和函数式编程能够通过调用C/C代码扩展功能代码规范程度高&a…...
怎么做网站优化 s/苏州百度推广公司地址
1.准备工作——安装一些工具包 $ sudo apt-get install ros-melodic-ros-tutorials ros-melodic-geometry-tutorials ros-melodic-rviz ros-melodic-rosbash ros-melodic-rqt-tf-tree2.运行demo roslaunch turtle_tf turtle_tf_demo.launch会跳出一个窗口,一只小乌…...
浙江华临建设集团有限公司网站/seo行业网
天龙八部(武侠世界)的源码很可能是天龙八部代码流出后改写的,因为在看了代码中可以找到一些证据,整个客户端分为:一个是编辑器,一个是客户端,采用OGREcegui自写的简单的物理碰撞检测FMOD自写的网络库。 服务器端代码目…...
商务网站建设与管理/百度长尾关键词挖掘工具
题目 原题链接 问题描述 我们以[b,q,y][b,q,y][b,q,y]表示以bbb为首元素,qqq为公差,yyy为序列个数的序列,如[−1,2,4][-1,2,4][−1,2,4]表示序列[−1,1,3,5][-1,1,3,5][−1,1,3,5]。 若存在两个序列AAA、BBB,它们的交集为序列CC…...