1.条件编译形式
2.Spring Bootå°è®°
3.预编译命令行由什么符号开头?
4.从 A|B 得到 A&B
条件编译形式
条件编译形式允许程序在运行时根据特定条件选择执行不同的代码块。这种形式通常用于在不同平台或配置下优化代码或实现兼容性。以 NNN 和 MMM 作为条件示例,其结构如下: #if NNNstatement1;
#elif MMM
statement2;
#else
statement3;
#endif
此结构中,`#if`、`#elif` 和 `#else` 是源码影视文化预处理器指令,用于根据 NNN 和 MMM 的值决定执行哪部分代码。当 NNN 为真(通常表示为1)时,执行 `statement1`;当 NNN 为假(通常表示为0)且 MMM 为真时,执行 `statement2`;当 NNN 和 MMM 均为假时,则执行 `statement3`。
条件编译的ipad 源码查看形式在软件开发中非常有用。它允许开发者在不修改源代码的情况下,针对不同环境或配置提供不同功能。例如,在编写跨平台应用时,可以使用条件编译来根据目标平台的特性选择使用特定的功能库或功能实现。这有助于减少代码冗余,提高代码效率和可维护性。 此外,条件编译还能用于在开发过程中进行调试和测试。通过条件地启用或禁用某些功能或代码块,开发者可以更容易地定位和解决问题。早期 打卡 源码在生产环境中,可以使用条件编译来禁用调试代码、日志记录或性能测试代码,从而减少应用程序的大小和运行时消耗。 总之,条件编译是一种强大的工具,能够根据运行环境和需求动态地调整程序的行为。它简化了代码维护和跨平台开发的过程,有助于提高软件的性能和可移植性。扩展资料
一般情况下,源程序中所有的tep补丁 源码行都参加编译。但有时希望对其中一部分内容只在满足一定条件下才进行编译,即对一部分内容指定编译条件,这就是“条件编译”(conditional compile)。条件编译语句排版时,需考虑以下三种位置:1)条件编译语句块与函数定义体之间不存在相互嵌套(主要在(.h)文件中);2)条件编译语句块嵌套在函数体之外(主要在(.c)文件中);3)条件编译语句嵌套在函数体内 (主要在(.c)文件中)。条件编译指令将决定那些代码被编译,而哪些是不被编译的。可根据表达式的值或某个特定宏是否被定义来确定编译条件。Spring Bootå°è®°
1ãApplicationContextInitializerï¼å¨Springä¸ä¸æ被å·æ°ä¹åè¿è¡åå§åçæä½ãè¿ä¸ªæ¶åå·²ç»å建äºApplicationContext ï¼ä½æ¯æ²¡ærefresh()ï¼ApplicationContextInitializer对ApplicationContextè¿è¡åå§è¯æä½ã2ãSpringApplicationRunListenerï¼å¯¹ApplicationContextçè¿è¡å个æ¶æçäºä»¶è¿è¡å¹¿æï¼æ¶äºä»¶è½å¤è¢«ApplicationListeneræçå¬å°ã
3ãRunnerï¼Springä¸ä¸æåç½®å¤ç Runnerså¯ä»¥æ¯ä¸¤ä¸ªæ¥å£çå®ç°ç±»ï¼ org.springframework.boot.ApplicationRunner org.springframework.boot.CommandLineRunner å ¶å®æ²¡æä»ä¹ä¸åä¹å¤ï¼é¤äºæ¥å£ä¸çrunæ¹æ³æ¥åçåæ°ç±»åæ¯ä¸ä¸æ ·ç以å¤ãä¸ä¸ªæ¯å°è£ 好çApplicationArgumentsç±»åï¼å¦ä¸ä¸ªæ¯ç´æ¥çStringä¸å®é¿æ°ç»ç±»åãå æ¤æ ¹æ®éè¦éæ©ç¸åºçæ¥å£å®ç°å³å¯ã
SpringBootå¯å¨çæ¶åï¼ä¸è®ºè°ç¨ä»ä¹æ¹æ³ï¼é½ä¼æé ä¸ä¸ªSpringApplicationçå®ä¾ï¼ç¶åè°ç¨è¿ä¸ªå®ä¾çrunæ¹æ³ï¼è¿æ ·å°±è¡¨ç¤ºå¯å¨SpringBootã
å¨runæ¹æ³è°ç¨ä¹åï¼ä¹å°±æ¯æé SpringApplicationçæ¶åä¼è¿è¡åå§åçå·¥ä½ï¼åå§åçæ¶åä¼å以ä¸å 件äºï¼
SpringApplicationæé å®æä¹åè°ç¨runæ¹æ³ï¼å¯å¨SpringApplicationï¼runæ¹æ³æ§è¡çæ¶åä¼å以ä¸å 件äºï¼
å¨@SpringBootApplicationæ ç¾ä¸å¼å ¥äºEnableAutoConfigurationImportSelectorï¼å ¶ä¸è°ç¨äºselectImports()æ¹æ³ï¼æ¹æ³ä¸è°ç¨org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector#getCandidateConfigurationsæ¹æ³ï¼ä½¿ç¨SpringFactoryLoaderæMETA-INFæ件夹ä¸çspring.factoriesæ件ä¸EnableAutoConfiguration为keyçæ件å è½½äºã å è½½çæä»¶å ¨é¨é½æ¯java configé ç½®æ件ï¼æé»è®¤é ç½®ï¼ï¼å©ç¨@Conditional(Class<? extends Condition>[]) æ ç¾ï¼å¯¹ç¸åºçbeanè¿è¡éæ©æ§çå è½½ã
æ¯è¾åºæ¬èä¸éè¦çä¸ä¸ªç±»ï¼è¿è¡å è½½äºMATE-INFä¸çspring.factories æ件
@Conditionalæ ç¾æ¯å ¨é¨Conditionalç¸å ³æ ç¾çæ ¹æºã æºç ä¸Conditionalæ ç¾ä½¿ç¨çæ¯ConditionEvaluatoræ¥è§£æï¼å¦ä¸ org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class<?>, java.lang.String, java.lang.Class<? extends java.lang.annotation.Annotation>...) org.springframework.context.annotation.ConditionEvaluator#shouldSkip(org.springframework.core.type.AnnotatedTypeMetadata, org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase)
å¨åå§åAnnotationConfigApplicationContextçæ¶åï¼å¯¹ConfigurationClassPostProcessorãAutowiredAnnotationBeanPostProcessorçç±»è¿è¡äºæ³¨åãå¦ä¸
ConfigurationClassPostProcessoræ¯ä¸ä¸ªBeanFactoryPostProcessorï¼æ以ä¼å¯¹BeanDefinitionRegistryæè BeanDefinitionå建ä¹åè¿è¡åç½®å å·¥ï¼refreshæ¹æ³ä¸ï¼å·²ç»å建äºBeanFactoryï¼å ·ä½å°è¿è¡å°åªéçæºç ï¼ã
import解æåçæ ¹æ®çæ¯ConfigurationClassPostProcessorï¼ConfigurationClassPostProcessorçå è½½è¿ç¨åèä¸é¢ 主è¦åæ为å¥@importæ ç¾æ¯å¼å ¥é ç½®çä½æ¯å´è½å¤è°ç¨Selectorçæ¹æ³ org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>) org.springframework.context.annotation.ConfigurationClassParser#processDeferredImportSelectors æ¥çå¦ä¸ï¼è°ç¨äºselectImportsæ¹æ³
预编译命令行由什么符号开头?
#号是官方定义的,用于和其他类型区别的,不用多考虑,试用源码破解你就看看我给你的链接看看官方的说法
条件编译符号#define
#if、#elif、#else 和 #endif 指令提供的条件编译功能是通过预处理表达式和条件编译符号来控制的。
conditional-symbol:(条件符号:)
除 true 和 false 外的任何标识符或关键字
条件编译符号有两种可能的状态:已定义的或未定义的。在源文件词法处理开始时,条件编译符号除非已由外部机制(如命令行编译器选项)显式定义,否则是未定义的。当处理 #define 指令时,在指令中指定的条件编译符号在那个源文件中成为已定义的。此后,该符号就一直保持已定义的状态,直到处理一条关于同一符号的 #undef 指令,或者到达源文件的结尾。这意味着一个源文件中的 #define 和 #undef 指令对同一程序中的其他源文件没有任何影响。
当在预处理表达式中引用时,已定义的条件编译符号具有布尔值 true,未定义的条件编译符号具有布尔值 false。不要求在预处理表达式中引用条件编译符号之前显式声明它们。相反,未声明的符号只是未定义的,因此具有值 false。
条件编译符号的命名空间与 C# 程序中的所有其他命名实体截然不同。只能在 #define 和 #undef 指令以及预处理表达式中引用条件编译符号。
从 A|B 得到 A&B
如何从 A|B 得到 A&B?
Stack Overflow 上有相关答案。
原因如下,我们来分解这个表达式:
第一部分是 U extends any ? (k: U) => void : never
第二部分是 extends ((k: infer I) => void) ? I : never
第一部分中,U extends any 是什么意思,为什么要判断是否 extends any?
具体可以参考这篇文章,简要来说,如果 extends 左边是联合类型,TypeScript 会将联合类型拆开进行判断。
如果输入是 1|2,那么输出是 ((k: 1) => void) | ((k: 2) => void),而不是 (k: 1|2) => void,这样就得到了多个函数的联合。
第二部分的意思是,如果左边是一个函数,那么就返回它的第一个参数的类型。
那么问题来了,为什么 ((k: 1) => void) | ((k: 2) => void) 的参数是 1&2?
因为函数参数是逆变的,我们假设有一个变量能同时传给 (k: 1) => void 和 (k: 2) => void,那么这个变量的类型应该是 1&2 而不是 1|2。
A extends B 意味着所有 B 都可以无条件被 A 替换。
一个函数能被 (k: 1) => void 和 (k: 2) => void 无条件替换,那么那个函数接受的参数必然既是1又是2。
但是,根据 conditional type 的特性,((k: 1) => void) | ((k: 2) => void) 不是应该被分开处理吗?如果分开处理,结果依然会是 1|2。
在苦思无果之后,TypeScript 核心贡献者@王文璐(也是 Vue 核心团队的成员)直接给我看了源码。
虽然我看得不太懂,但大概意思是,extends 左边联合类型被拆开判断的情况只会出现在左边是一个类型参数的情况。
大概就是 type F = T extends xxx 的这个左边会被拆开,而 type F = T|1 extends xxx 的左边就不会被拆开。
我还是一头雾水。
完。
2024-12-22 16:02
2024-12-22 15:43
2024-12-22 15:35
2024-12-22 15:04
2024-12-22 14:48
2024-12-22 14:45