diff --git a/AI/mechine learning/AWS.md b/AI/mechine learning/AWS.md
new file mode 100644
index 0000000..fea068c
--- /dev/null
+++ b/AI/mechine learning/AWS.md
@@ -0,0 +1,129 @@
+# AWS
+
+> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
+> 分类 ID:`2022050510233200000000000005` · 排序:6 · 文章数:7
+
+## 目录
+
+1. [S3](#s3)
+2. [EC2](#ec2)
+3. [Route 53](#route-53)
+4. [VPC](#vpc)
+5. [AWS Storage Gateway](#aws-storage-gateway)
+6. [Amazon Kinesis](#amazon-kinesis)
+7. [AWS STS](#aws-sts)
+
+---
+
+## 1. S3
+
+bid: `2022050510233300000000000006`
+
+### simple storage service
+---
+[Price文档](https://aws.amazon.com/cn/s3/pricing/)
+S3的收费内容,包括:
+存储,请求(http请求数量),数据传输(宽带费用),复制(跨区域和不跨区域),管理(额外的高级管理功能)
+
+
+### Enable Requester Pays
+---
+[官方文档](https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/RequesterPaysBuckets.html)
+作为SAP考试中的一题,重要考察的是:存储桶的拥有者和访问者分开付费。两个不同的付费账户,访问者需要身份验证。
+关键词:**Enable Requester Pays**,**AWS credentials**
+
+### Replicating objects
+---
+[官方文档](https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication.html#crr-scenario)
+**Cross-Region Replication** 跨区域复制 **CRR**
+
+**Same-Region Replication** 同区域复制 **SRR**
+
+---
+
+## 2. EC2
+
+bid: `2022050510458100000000000007`
+
+
+
+---
+
+## 3. Route 53
+
+bid: `2022050510575300000000000008`
+
+
+
+---
+
+## 4. VPC
+
+bid: `2022050511086300000000000009`
+
+### Amazon Virtual Private Cloud
+---
+私有云
+[官方文档](https://docs.aws.amazon.com/zh_cn/vpc/?id=docs_gateway)
+
+PVC的CIDR是 16位,
+PVC的子网的CIDR是24位,
+同一个区域的两个VPC,最好的解决方式是peering connection,并在路由表中添加路由
+
+### VPC peering
+---
+ VPC 对等连接是两个 VPC 之间的网络连接,通过此连接,您可以使用私有 IPv4 地址或 IPv6 地址在两个 VPC 之间路由流量。这两个 VPC 中的实例可以彼此通信,就像它们在同一网络中一样。您可以在自己的 VPC 之间创建 VPC 对等连接,或者在自己的 VPC 与其他AWS账户中的 VPC 之间创建连接。VPC 可位于不同区域内(也称为区域间 VPC 对等连接)
+ AWS使用 VPC 的现有基础设施来创建 VPC 对等连接;该连接既不是网关也不是 VPN 连接,并且不依赖某一单独的物理硬件。没有单点通信故障也没有带宽瓶颈。
+ 创建 VPC 对等连接,无需付费。通过对等连接进行数据传输需要付费。
+ 要将私有 IPv4 流量从实例发送到对等 VPC 中的实例,必须向与实例所在子网关联的路由表添加路由。此路由指向 VPC 对等连接中对等 VPC 的 CIDR 块(或 CIDR 块的一部分),并指定 VPC 对等连接作为目标。
+### AWS Transit Gateway
+---
+[中转网关工作原理](https://docs.aws.amazon.com/zh_cn/vpc/latest/tgw/how-transit-gateways-work.html)
+中转网关是网络中转中心,您可用它来互连 Virtual Private Cloud (VPC) 和本地网络.
+中转网关独立存在,有中转网关路由表,可以挂载VPC,AWS Direct Connect,对等连接的另一个Transit Gateway,VPN链接,和第三方设备
+中转网关既可以共享,也可以通过CloudWatch和CloudTrail进行监控。
+### AWS PrivateLink
+---
+ AWS PrivateLink 是一项具有高可用性的可扩展技术,支持您将您的 VPC 私密地连接到支持的 AWS 服务、由其他 AWS 账户托管的服务(VPC 终端节点服务)以及支持的 AWS Marketplace 合作伙伴服务。您无需使用互联网网关、NAT 设备、公有 IP 地址、AWS Direct Connect 连接或 AWS Site-to-Site VPN 连接,就能与该服务通信。因此,您可以控制可从 VPC 访问的特定 API 终端节点、站点和服务。
+
+ 请区分终端节点和终端节点服务。
+
+ 私有链接通过终端节点来实现,终端节点包括:
+接口终端节点:
+网关终端节点:
+网关负载均衡器终端节点:
+
+---
+
+## 5. AWS Storage Gateway
+
+bid: `2022050513596500000000000010`
+
+**提供几乎不受限制的云存储的本地应用程序访问权限**
+[官方文档](https://aws.amazon.com/cn/storagegateway/?nc1=h_ls)
+
+---
+
+## 6. Amazon Kinesis
+
+bid: `2022050514188900000000000011`
+
+对标于flume,Kafka,和flink的分布式云计算模式。
+[官方文档](https://aws.amazon.com/cn/kinesis/)
+**Amazon Kinesis Data Streams** 其实和flume很像
+ 日志采集传输,sink
+**Amazon Kinesis Data Firehose** 其实和kafka很像
+ 消息队列,存储
+**Amazon Kinesis Data Analytics** 其实和flink很像
+ 流式计算
+
+---
+
+## 7. AWS STS
+
+bid: `2022050911184000000000000004`
+
+
+AWS Security Token Service (STS)
+
+---
diff --git a/AI/mechine learning/Azure.md b/AI/mechine learning/Azure.md
new file mode 100644
index 0000000..6ee8bfc
--- /dev/null
+++ b/AI/mechine learning/Azure.md
@@ -0,0 +1,154 @@
+# Azure
+
+> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
+> 分类 ID:`2022052309468900000000000004` · 排序:8 · 文章数:8
+
+## 目录
+
+1. [Iot Hub Endpoint](#iot-hub-endpoint)
+2. [Iot Hub Message routing](#iot-hub-message-routing)
+3. [Azure IoT Hub Device Provisioning Service (DPS)](#azure-iot-hub-device-provisioning-service-dps)
+4. [Batch Shipyard](#batch-shipyard)
+5. [Azure system](#azure-system)
+6. [pricing](#pricing)
+7. [Azure IoT Edge](#azure-iot-edge)
+8. [pvc](#pvc)
+
+---
+
+## 1. Iot Hub Endpoint
+
+bid: `2022052309469000000000000009`
+
+### endpoints
+---
+[IoT Hub endpoints](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-endpoints)
+
+## IoT Hub names
+ You can find the hostname of the IoT hub that hosts your endpoints in the portal on your hub's Overview page.
+ By default, the DNS name of an IoT hub looks like: {your iot hub name}.azure-devices.net.
+
+## List of built-in IoT Hub endpoints
+ 1. Device identity management
+ 2. Device twin management
+ 3. Jobs management
+ 4. Device endpoints
+ 5. Service endpoints
+ 6. Resource provider.
+
+## Custom endpoints
+ 1. Azure Storage containers
+ 2. Event Hubs
+ 3. Service Bus Queues
+ 4. Service Bus Topics
+
+
+## Endpoint Health
+
+## Field gateways
+ In an IoT solution, a field gateway sits between your devices and your IoT Hub endpoints.
+ It is typically located close to your devices.
+ You can use Azure IoT Edge to implement a field gateway.
+ IoT Edge offers functionality such as multiplexing communications from multiple devices onto the same IoT Hub connection.
+
+---
+
+## 2. Iot Hub Message routing
+
+bid: `2022052310025600000000000010`
+
+Message routing
+---
+[Message routing](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messages-d2c)
+
+---
+
+## 3. Azure IoT Hub Device Provisioning Service (DPS)
+
+bid: `2022052310265300000000000011`
+
+### Azure IoT Hub Device Provisioning Service (DPS)
+---
+[DPS](https://docs.microsoft.com/en-us/azure/iot-dps/?WT.mc_id=Portal-Microsoft_Azure_IotHub)
+
+## what is
+ Microsoft Azure provides a rich set of integrated public cloud services for all your IoT solution needs.
+ The IoT Hub Device Provisioning Service (DPS) is a helper service for IoT Hub that enables zero-touch, just-in-time provisioning to the right IoT hub without requiring human intervention.
+ DPS enables the provisioning of millions of devices in a secure and scalable manner.
+
+##
+
+---
+
+## 4. Batch Shipyard
+
+bid: `2022052313361500000000000012`
+
+## Batch Shipyard
+---
+[doc](https://batch-shipyard.readthedocs.io/en/latest/00-introduction/)
+
+---
+
+## 5. Azure system
+
+bid: `2022052313512900000000000013`
+
+1.active directory
+2.subscriptions
+3.Resource groups
+4.
+
+azure 基本上是个网格体系
+
+---
+
+## 6. pricing
+
+bid: `2022052314413800000000000015`
+
+## Pricing Options
+---
+[doc](https://azure.microsoft.com/ja-jp/pricing/details/iot-hub/#purchase-options)
+
+---
+
+## 7. Azure IoT Edge
+
+bid: `2022052410596000000000000017`
+
+## Modules
+---
+[doc](https://docs.microsoft.com/en-us/azure/iot-edge/iot-edge-modules?view=iotedge-2020-11)
+
+ IoT Edge modules are Docker containers deployed to IoT Edge devices.
+ They can communicate with other modules or send data to the IoT Edge runtime.
+ Azure IoT Edge lets you deploy and manage business logic on the edge in the form of modules.
+ Azure IoT Edge modules are the smallest unit of computation managed by IoT Edge, and can contain Azure services (such as Azure Stream Analytics) or your own solution-specific code.
+ To understand how modules are developed, deployed, and maintained, consider the four conceptual elements of a module:
+
+## Routes
+---
+[doc](https://docs.microsoft.com/ja-jp/azure/iot-edge/module-composition?view=iotedge-2020-11#declare-routes)
+
+
+## IoT Edge deployments
+---
+[doc](https://docs.microsoft.com/ja-jp/azure/iot-edge/module-deployment-monitoring?view=iotedge-2020-11)
+
+ IoT Edge deployments configure sets of IoT Edge devices to run IoT Edge modules.
+ Each deployment continuously ensures that all matching devices are running the specified set of modules, even when new devices are created or are modified to match the target condition.
+
+ Two modules are required in every deployment manifest: $edgeAgent, and $edgeHub.
+
+ These modules are part of the IoT Edge runtime that manages the IoT Edge device and the modules running on it.
+
+---
+
+## 8. pvc
+
+bid: `2022110910113500000000000002`
+
+
+
+---
diff --git a/AI/mechine learning/Golang.md b/AI/mechine learning/Golang.md
new file mode 100644
index 0000000..c1b3c01
--- /dev/null
+++ b/AI/mechine learning/Golang.md
@@ -0,0 +1,199 @@
+# Golang
+
+> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
+> 分类 ID:`2023022315480800000000000001` · 排序:12 · 文章数:4
+
+## 目录
+
+1. [3. grpc xds](#3-grpc-xds)
+2. [2. grpc health check](#2-grpc-health-check)
+3. [1. grpc protoc](#1-grpc-protoc)
+4. [4. Go](#4-go)
+
+---
+
+## 1. 3. grpc xds
+
+bid: `2023022315480900000000000020`
+
+该写点什么么...
+
+---
+
+## 2. 2. grpc health check
+
+bid: `2023022315484500000000000019`
+
+##
+
+---
+
+## 3. 1. grpc protoc
+
+bid: `2023022315507600000000000021`
+
+## base consepts
+
+- protobuf
+
+我们可以查看官方文档 [protobuf guides](https://protobuf.dev/programming-guides/proto3/)
+
+简单来说就是一种以 .proto 结尾文件,遵循protocol buffer language 语法,其中包含一个或者多个message和service。
+
+**notice_service.proto**
+
+ syntax = "proto3";
+
+ package notice.service.v1;
+
+ option go_package ="violin-notice/pkg/service/notice.service.v1";
+
+ message NoticeMessage {
+
+ };
+
+ message NoticeResponse {};
+
+ service NoticeService {
+ rpc SendNotice(NoticeMessage) returns (NoticeResponse) {}
+ }
+
+- protoc
+[protoc guides](https://github.com/bufbuild/protoc-gen-validate)
+
+作为可执行程序,其作用是将上面的我们定义的.proto文件转换成对应语言的grpc 可用的文件,我们通过对这些文件进行扩展来实现我们想要的场景。
+
+ protoc --go_out=./gen --go_opt=paths=source_relative --go-grpc_out=./gen --go-grpc_opt=paths=source_relative notice_service.proto
+
+执行上面命令会生成go语言的两个文件
+
+ notice_service_grpc.pb.go
+ notice_service.pb.go
+
+我们只需要自己写一个notice_service.go 来扩展上述两个文件即可。
+
+**package notice_service_v1**
+
+ import (
+ "context"
+ "gopkg.in/gomail.v2"
+ "log"
+ "violin-home.cn/common/logs"
+ )
+
+ type NoticeService struct {
+ UnimplementedNoticeServiceServer
+ }
+
+ func New() *NoticeService {
+ return &NoticeService{}
+ }
+
+
+ func (*NoticeService) SendNotice(
+ ctx context.Context, msg *NoticeMessage) (*NoticeResponse, error) {
+
+ // to write logic
+ return &NoticeResponse{}, nil
+ }
+
+
+ ## 如何使用grpc
+
+ grpc 存在client和server
+
+---
+
+## 4. 4. Go
+
+bid: `2023030213489100000000000022`
+
+## 1. 概述
+一些简单的概念介绍可以通过下面网站学习到。
+[golang 菜鸟教程](https://www.runoob.com/go/go-tutorial.html)
+
+## 2. package
+
+golang的包管理模式是树形的,并且有以下规约:
+**1**
+树形结构的根节点是main,即项目根目录。
+**2**
+文件中的包定义 一定是和该文件所处的文件夹相同
+**3**
+文件中定义的函数,如果是像作为第三方包引用,函数的首字母必须大写
+
+ # violin-controller 工程为例 https://github.com/simple321vip/violin-controller
+ ls
+ main.go controller.go controller_test.go 都是 根目录下的文件,所以他们的package 都是 main
+ 请注意 包 的名字只能是该文件夹的名字,并不包括父级路径
+
+**4 引包**
+引包 包括第三方包 和 项目自定义包
+在mod模式下,第三方包存在 \$GOPATH/pkg/mod
+而自定义包 引入的时候直接从采用 项目相对路径的方式引入
+
+## 3. 变量与指针
+
+变量分为 值变量和指针变量
+
+## 4. 函数
+
+**1. main()** 函数
+
+程序入口函数
+
+**2. init()** 函数
+
+每一个源文件都可以包含一个init函数,init意为初始化,也表明init函数会在main函数执行之前执行。
+
+**3. go func()** 函数
+
+并发编程 即异步
+
+**4. func() {}()** 匿名函数
+
+匿名函数可以通过变量指向匿名函数,可以匿名函数直接执行
+
+ // 声明一个函数变量
+ f := func() int {
+ return 1
+ }
+
+ // 调用函数
+ f()
+
+ // 也可以直接执行匿名函数
+ func() int {
+ return 1
+ }()
+
+**5. func sample() func() int {}** 通过匿名函数实现闭包
+
+ package main
+
+ import "fmt"
+
+ func getSequence() func() int {
+ i:=0
+ return func() int {
+ i+=1
+ return i
+ }
+ }
+
+ func main(){
+ /* nextNumber 为一个函数,函数 i 为 0 */
+ nextNumber := getSequence()
+
+ /* 调用 nextNumber 函数,i 变量自增 1 并返回 */
+ fmt.Println(nextNumber())
+ fmt.Println(nextNumber())
+ fmt.Println(nextNumber())
+
+ /* 创建新的函数 nextNumber1,并查看结果 */
+ nextNumber1 := getSequence()
+ fmt.Println(nextNumber1())
+ fmt.Println(nextNumber1())
+ }
+
+---
diff --git a/AI/mechine learning/Java and Spring.md b/AI/mechine learning/Java and Spring.md
new file mode 100644
index 0000000..c0248d7
--- /dev/null
+++ b/AI/mechine learning/Java and Spring.md
@@ -0,0 +1,659 @@
+# Java and Spring
+
+> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
+> 分类 ID:`00000000000002` · 排序:1 · 文章数:14
+
+## 目录
+
+1. [Springboot AbstractApplicationContext](#springboot-abstractapplicationcontext)
+2. [Map Set List](#map-set-list)
+3. [Java8 AQS](#java8-aqs)
+4. [Java8 Stream](#java8-stream)
+5. [Spring superinterface](#spring-superinterface)
+6. [Springboot DefaultSingletonBeanRegistry](#springboot-defaultsingletonbeanregistry)
+7. [Springboot SpringApplication](#springboot-springapplication)
+8. [Springboot AbstractBeanFactory](#springboot-abstractbeanfactory)
+9. [Springboot AbstractAutowireCapableBeanFactory](#springboot-abstractautowirecapablebeanfactory)
+10. [Springboot AbstractBeanDefinition](#springboot-abstractbeandefinition)
+11. [Springboot ConfigurationClassPostProcessor](#springboot-configurationclasspostprocessor)
+12. [Spring ASM](#spring-asm)
+13. [PostProcessorRegistrationDelegate](#postprocessorregistrationdelegate)
+14. [Spring Aop](#spring-aop)
+
+---
+
+## 1. Springboot AbstractApplicationContext
+
+bid: `00000000000003`
+
+## AbstractApplicationContext
+
+ AbstractApplicationContext 是 SpringBoot的 核心应用上下文父类。
+
+## x.1 properties
+
+### beanFactoryPostProcessors
+
+### environment
+
+## x.2 methods
+
+### refresh
+
+ refresh 是 Springboot启动中核心方法。
+
+- prepareRefresh
+- obtainFreshBeanFactory
+- prepareBeanFactory
+- postProcessBeanFactory
+- invokeBeanFactoryPostProcessors
+- registerBeanPostProcessors
+- onRefresh
+- finishBeanFactoryInitialization
+- finishRefresh
+
+---
+
+## 2. Map Set List
+
+bid: `2022051816085000000000000006`
+
+### 1. Summary
+
+ 我们在开发过程在,最常见的三种数据存储结构就是 Map Set 和List了
+
+ 这三种结构最明显的特征就是Map 是键值,Set是对象存储唯一,List是有序数组
+
+
+### Map
+
+ 键值存储,主键不允许重复
+
+ 添加元素 使用put方法,如果key重复,则value被覆盖
+
+### Set
+
+ 对象存储,对象不允许重复
+
+ /**
+ * if this set did not already contain the specified element will return {@code true}
+ * f this set already contains the element, the call leaves the set
+ * unchanged and returns {@code false}
+ */
+ public boolean add(E e)
+
+### List
+
+ list是由数组构成的,这就意味着,list是有顺序的,因为数组在内存中是一段连续的内存。
+
+---
+
+## 3. Java8 AQS
+
+bid: `2022052314143400000000000014`
+
+## AQ
+
+---
+
+## 4. Java8 Stream
+
+bid: `2022060810550500000000000022`
+
+## S
+
+---
+
+## 5. Spring superinterface
+
+bid: `2022120915183100000000000001`
+
+## summary
+
+
+## 1. Aware(感知)
+
+Spring Ioc 是解耦行为,我们的业务代码其实是没有感知或者意识到spring框架的存在。如果我们需要使用spring Ioc中的资源时候,我们就需要有意识的去获取这个资源,而Aware 就是这样的存在。
+
+ @Service
+ public class AppContextAware implements ApplicationContextAware {
+ ApplicationContext applicationContext;
+
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext=applicationContext;
+ }
+
+ public void hello(){
+ //user为容器中存在的bean
+ User user = applicationContext.getBean("user", User.class);
+ System.out.println(user);
+
+ //获取容器的环境、User.name为设置好的属性
+ Environment environment = applicationContext.getEnvironment();
+ String property = environment.getProperty("User.name");
+ System.out.println(" 属性:"+property);
+ }
+ }
+
+ 一些常用的Aware interface
+ BeanNameAware
+ ApplicationContextAware
+ ResourceLoaderAware
+ EnvironmentAware
+
+
+
+## 2. BeanFactory
+
+BeanFactory 提供了获取bean和判断bean的方法,包括
+
+ getBean(String beanName)
+ getBean(String beanName, Class requiredType)
+ getBean(Class requiredType)
+ containsBean(String name)
+ isSingleton(String name)
+ isPrototype(String name)
+ sTypeMatch(String name)
+ getType(String name)
+ String[] getAliases(String name);
+
+## 3. BeanPostProcessor
+
+## 4. BeanFactoryPostProcessor
+
+## 5. ApplicationContext
+
+## 6. InitializingBean
+
+---
+
+## 6. Springboot DefaultSingletonBeanRegistry
+
+bid: `2022121513519200000000000002`
+
+## DefaultSingletonBeanRegistry
+
+DefaultSingletonBeanRegistry 是Springboot bean 自动装配的核心实现类。
+顾名思义,是默认的单例bean 注册器。
+
+## x.1 properties
+
+### dependentBeanMap
+
+ 存放(依赖对象key -> 被依赖Set)的 ConcurrentHashMap
+ private final Map> dependentBeanMap = new ConcurrentHashMap<>(64);
+
+### dependenciesForBeanMap
+
+ 存放(被依赖对象key -> 依赖Set)的 ConcurrentHashMap
+ private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
+###
+
+## x.2 methods
+
+### registerDependentBean
+
+我们知道Spring DI 依赖注入,此方法就是依赖注入的核心组成。注意,这段逻辑是加锁的,即存在并行处理逻辑。
+Springboot 在 AbstractApplicationContext 进行 refresh 操作时候,在最后一步会实例化bean,参照AbstractApplicationContext.finishBeanFactoryInitialization 方法,此方法的流程我们会在xxx讲解。源码如下
+
+
+ /**
+ * Register a dependent bean for the given bean。
+ */
+ public void registerDependentBean(String beanName, String dependentBeanName) {
+ String canonicalName = canonicalName(beanName);
+ synchronized (this.dependentBeanMap) {
+ Set dependentBeans =
+ this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
+ if (!dependentBeans.add(dependentBeanName)) {
+ return;
+ }
+ }
+
+ synchronized (this.dependenciesForBeanMap) {
+ Set dependenciesForBean =
+ this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
+ dependenciesForBean.add(canonicalName);
+ }
+
+ }
+
+DI 在此处的实现逻辑可以通过下面例子来通俗说明:
+ ① A对象 依赖 B对象
+ ② A对象 依赖 C对象
+ ③ D对象 依赖 B对象
+ 所以 必须要提前先把 B 对象和 C对象进行实例化后,才能 创建A对象和 D对象。
+我们从RootBeanDefinition中获取 dependsOn的数组,遍历调用registerDependentBean方法
+参数beanName是依赖对象,即 B 或者 C,参数dependentBeanName是被依赖对象A
+1. 传入参数是 (B,A) 时,为 B 创建一个 LinkedHashSet,并在该Set中存放A, 并把 B -> Set的映射关系放入dependentBeanMap中。
+紧接着 为 A 创建一个 LinkedHashSet, 并在该Set中存放B,并把 A -> Set的映射关系放入dependenciesForBeanMap中。
+2. 传入参数是 (C, A) 时,为 C 创建一个 LinkedHashSet,并在该Set中存放A, 并把 C -> Set的映射关系放入dependentBeanMap中。
+因为 dependenciesForBeanMap 已经存在了 A -> Set这个映射,我们只需将 C 也存入这个Set就可以。
+3. 传入参数是 (B, D) 时,因为 dependentBeanMap 已经存在了 B -> Set这个映射,我们只需将 D 也存入这个Set就可以。
+紧接着 为 D 创建一个 LinkedHashSet, 并在该Set中存放B,并把 D -> Set的映射关系放入dependenciesForBeanMap中。
+
+`注意` 依赖和被依赖总是成对出现的,dependentBeans.add(dependentBeanName) 返回 false,视为添加失败,即视为已经存在,根据 依赖和被依赖总是成对出现的,所以后面dependenciesForBean.add(canonicalName) 这部分就没必要执行了,因为执行了也没有意义,所以直接 return了。毕竟dependenciesForBean中已经存在了canonicalName。
+
+---
+
+## 7. Springboot SpringApplication
+
+bid: `2022121513597200000000000003`
+
+## SpringApplication
+
+## x.1 properties
+
+### sources
+
+### environment
+
+### webApplicationType
+
+###
+
+## x.2 methods
+
+### run
+
+1. 创建 DefaultBootstrapContext
+2. 获取 SpringApplicationRunListeners
+3. 转换 ApplicationArguments 将commandLine args
+4. 装备环境 ConfigurableEnvironment
+5. 配置忽略bean情报 configureIgnoreBeanInfo
+6. 创建 ApplicationContext
+7. 准备 ApplicationContext prepareContext
+设置上下文环境,加载source
+8. 刷新 ApplicationContext
+9. 刷新后处理
+
+---
+
+## 8. Springboot AbstractBeanFactory
+
+bid: `2022121515315000000000000004`
+
+## AbstractBeanFactory
+
+
+## x.2 methods
+
+### doGetBean
+AbstractBeanFactory 的核心方法 doGetBean,doGetBean方法是由getBean调用的,如果有dependsOn存在,就会将注册依赖, 然调用getBean(dep),从而形成了递归操作。
+当不存dependsOn的时候mbd.isSingleton 时候,就会调用 getSingleton方法,子类会回调createBean(beanName, mbd, args)方法,去创建bean。
+
+源码
+
+ protected T doGetBean(String name, @Nullable Class requiredType) {
+ String beanName = transformedBeanName(name);
+ RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
+ checkMergedBeanDefinition(mbd, beanName, args);
+
+ // Guarantee initialization of beans that the current bean depends on.
+ String[] dependsOn = mbd.getDependsOn();
+ if (dependsOn != null) {
+ for (String dep : dependsOn) {
+ if (isDependent(beanName, dep)) {
+ throw new BeanCreationException(mbd.getResourceDescription(), beanName,
+ "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
+ }
+ registerDependentBean(dep, beanName);
+ try {
+ getBean(dep);
+ }
+ catch (NoSuchBeanDefinitionException ex) {
+ throw new BeanCreationException(mbd.getResourceDescription(), beanName,
+ "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
+ }
+ }
+ }
+
+ // Create bean instance.
+ if (mbd.isSingleton()) {
+ sharedInstance = getSingleton(beanName, () -> {
+ try {
+ return createBean(beanName, mbd, args);
+ }
+ catch (BeansException ex) {
+ // Explicitly remove instance from singleton cache: It might have been put there
+ // eagerly by the creation process, to allow for circular reference resolution.
+ // Also remove any beans that received a temporary reference to the bean.
+ destroySingleton(beanName);
+ throw ex;
+ }
+ });
+ beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
+ }
+ }
+
+---
+
+## 9. Springboot AbstractAutowireCapableBeanFactory
+
+bid: `2022121523309700000000000005`
+
+## AbstractAutowireCapableBeanFactory
+
+父类是AbstractBeanFactory,实现了AutowireCapableBeanFactory 的方法,其中最主要的还是createBean方法。
+源码
+
+ /**
+ * Central method of this class: creates a bean instance,
+ * populates the bean instance, applies post-processors, etc.
+ * @see #doCreateBean
+ */
+ @Override
+ protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
+ throws BeanCreationException {
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("Creating instance of bean '" + beanName + "'");
+ }
+ RootBeanDefinition mbdToUse = mbd;
+
+ // Make sure bean class is actually resolved at this point, and
+ // clone the bean definition in case of a dynamically resolved Class
+ // which cannot be stored in the shared merged bean definition.
+ Class> resolvedClass = resolveBeanClass(mbd, beanName);
+ if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
+ mbdToUse = new RootBeanDefinition(mbd);
+ mbdToUse.setBeanClass(resolvedClass);
+ }
+
+ // Prepare method overrides.
+ try {
+ mbdToUse.prepareMethodOverrides();
+ }
+ catch (BeanDefinitionValidationException ex) {
+ throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
+ beanName, "Validation of method overrides failed", ex);
+ }
+
+ try {
+ // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
+ Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
+ if (bean != null) {
+ return bean;
+ }
+ }
+ catch (Throwable ex) {
+ throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
+ "BeanPostProcessor before instantiation of bean failed", ex);
+ }
+
+ try {
+ Object beanInstance = doCreateBean(beanName, mbdToUse, args);
+ if (logger.isTraceEnabled()) {
+ logger.trace("Finished creating instance of bean '" + beanName + "'");
+ }
+ return beanInstance;
+ }
+ catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
+ // A previously detected exception with proper bean creation context already,
+ // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
+ throw ex;
+ }
+ catch (Throwable ex) {
+ throw new BeanCreationException(
+ mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
+ }
+ }
+
+---
+
+## 10. Springboot AbstractBeanDefinition
+
+bid: `2022121523361800000000000006`
+
+## AbstractBeanDefinition
+
+AbstractBeanDefinition 定义了 一个bean的各种描述。
+
+## x.1
+
+### String[] dependsOn
+
+### Resource resource
+
+###
+
+---
+
+## 11. Springboot ConfigurationClassPostProcessor
+
+bid: `2022121612282000000000000009`
+
+## ConfigurationClassPostProcessor
+
+这一节主要讲的是ConfigurationClassPostProcessor和他的一些生态。
+他的生态有
+- ConfigurationClassParser 真正的处理者。
+- ComponentScanAnnotationParser 扫描classpath,把beanName加入到registry的beanDefinitionMap中。
+- doProcessConfigurationClass 是该 postProcessor最核心的处理方法
+
+ /**
+ * Apply processing and build a complete {@link ConfigurationClass} by reading the
+ * annotations, members and methods from the source class. This method can be called
+ * multiple times as relevant sources are discovered.
+ * @param configClass the configuration class being build
+ * @param sourceClass a source class
+ * @return the superclass, or {@code null} if none found or previously processed
+ */
+ @Nullable
+ protected final SourceClass doProcessConfigurationClass(
+ ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
+ throws IOException {
+
+ if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
+ // Recursively process any member (nested) classes first
+ processMemberClasses(configClass, sourceClass, filter);
+ }
+ // Process any @PropertySource annotations
+ for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
+ sourceClass.getMetadata(), PropertySources.class,
+ org.springframework.context.annotation.PropertySource.class)) {
+ if (this.environment instanceof ConfigurableEnvironment) {
+ processPropertySource(propertySource);
+ }
+ else {
+ logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
+ "]. Reason: Environment must implement ConfigurableEnvironment");
+ }
+ }
+ // Process any @ComponentScan annotations
+ Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
+ sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
+ if (!componentScans.isEmpty() &&
+ !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
+ for (AnnotationAttributes componentScan : componentScans) {
+ // The config class is annotated with @ComponentScan -> perform the scan immediately
+ Set scannedBeanDefinitions =
+ this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
+ // Check the set of scanned definitions for any further config classes and parse recursively if needed
+ for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
+ BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
+ if (bdCand == null) {
+ bdCand = holder.getBeanDefinition();
+ }
+ if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
+ parse(bdCand.getBeanClassName(), holder.getBeanName());
+ }
+ }
+ }
+ }
+
+ // Process any @Import annotations
+ processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
+
+ // Process any @ImportResource annotations
+ AnnotationAttributes importResource =
+ AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
+ if (importResource != null) {
+ String[] resources = importResource.getStringArray("locations");
+ Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
+ for (String resource : resources) {
+ String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
+ configClass.addImportedResource(resolvedResource, readerClass);
+ }
+ }
+
+ // Process individual @Bean methods
+ Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
+ for (MethodMetadata methodMetadata : beanMethods) {
+ configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
+ }
+
+ // Process default methods on interfaces
+ processInterfaces(configClass, sourceClass);
+
+ // Process superclass, if any
+ if (sourceClass.getMetadata().hasSuperClass()) {
+ String superclass = sourceClass.getMetadata().getSuperClassName();
+ if (superclass != null && !superclass.startsWith("java") &&
+ !this.knownSuperclasses.containsKey(superclass)) {
+ this.knownSuperclasses.put(superclass, configClass);
+ // Superclass found, return its annotation metadata and recurse
+ return sourceClass.getSuperClass();
+ }
+ }
+
+ // No superclass -> processing is complete
+ return null;
+ }
+
+---
+
+## 12. Spring ASM
+
+bid: `2022121615335100000000000010`
+
+## asm
+
+在spring中其实很少听到asm这个关键字,asm -> Assembly,跟多是指汇编语言。
+
+spring也是用到asm,而且asm包是spring-core的组成部分。spring asm 大体上跟 原生的asm 都是差不多了。
+
+(参照链接)[ https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/asm/package-summary.htm ]
+
+
+ package org.springframework.asm
+ Spring's repackaging of ASM 9.x (with Spring-specific patches; for internal use only).
+ This repackaging technique avoids any potential conflicts with dependencies on ASM at the application level or from third-party libraries and frameworks.
+
+ As this repackaging happens at the class file level, sources and javadocs are not available here.
+
+从package-info可以看出,repackaging,avoids any potential conflicts
+
+---
+
+## 13. PostProcessorRegistrationDelegate
+
+bid: `2022121915527600000000000011`
+
+## PostProcessorRegistrationDelegate
+
+作为 Delegate 提供了 静态方法 invokeBeanFactoryPostProcessors。
+
+主要是将beanFactory和beanFactoryPostProcessors做matching,
+然后对beanFactoryPostProcessors做遍历调用postProcessBeanFactory(beanFactory)
+
+## ConfigurationClassPostProcessor
+
+postProcessBeanFactory(beanFactory)
+
+processConfigBeanDefinitions(beanFactory)
+
+核心的 处理方法,
+
+---
+
+## 14. Spring Aop
+
+bid: `2022122715594900000000000012`
+
+## Aop
+Aspect Oriented Programming的缩写,意为:面向切面编程。
+Spring aop 作为spring的一个模块,在springboot中是在bean的实例化中使用的。
+
+AbstractAutowireCapableBeanFactory#initializeBean
+
+
+ protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
+ if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged((PrivilegedAction