spring-reading./spring-core/spring-core-getBean/README.md

827 lines
39 KiB
Markdown
Raw Normal View History

2023-10-24 10:02:43 +00:00
## getBean
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
### 一、基本信息
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
✒️ **作者** - Lex 📝 **博客** - [我的CSDN]() 📚 **文章目录** - [所有文章](https://github.com/xuchengsheng/spring-reading) 🔗 **源码地址** - [getBean源码](https://github.com/xuchengsheng/spring-reading/tree/master/spring-core/spring-core-getBean)
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
### 二、方法描述
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
在 Spring 框架中,`getBean` 方法是 `ApplicationContext` 接口中的一个核心方法,用于从 Spring 容器中检索 bean。Spring 的核心是控制反转Inversion of Control, IoC和依赖注入Dependency Injection, DI`getBean` 方法正是实现这两个核心概念的重要方法。
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
### 三、方法源码
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
这个方法的定义和说明表明了 Spring IoC 容器的一些核心概念和工作机制。当你请求一个 bean 时Spring 会查找该 bean、处理任何别名、检查其作用域例如单例或原型并最终返回适当的 bean 实例给调用者。
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
```java
/**
* 返回指定bean的实例该实例可能是共享的或独立的。
* 此方法使Spring BeanFactory可以替代单例或原型设计模式。在单例bean的情况下调用者可以保留返回对象的引用。
* 将别名转换回相应的规范bean名称。
* 如果在这个工厂实例中找不到bean将询问父工厂。
*
* @param name 要检索的bean的名称
* @return bean的实例
* @throws NoSuchBeanDefinitionException 如果没有指定名称的bean
* @throws BeansException 如果无法获取bean
*/
Object getBean(String name) throws BeansException;
```
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
### 四、主要功能
1. **检索 Bean**
+ 从 Spring 容器中检索并返回指定名称或类型的 bean 的实例。
2. **作用域处理**
+ 根据 bean 的配置和作用域(例如 "singleton" 或 "prototype"`getBean` 可以返回单例的 bean 实例或每次都创建一个新的实例。
3. **别名处理**
+ 如果 bean 有别名,`getBean` 可以根据这些别名解析并返回相应的 bean 实例。
4. **考虑父容器**
+ 如果在当前容器中找不到 bean但容器有父容器`getBean` 会在父容器中查找该 bean。
5. **类型转换**
+ `getBean` 还有一个重载版本,允许用户指定返回 bean 的类型,这样可以避免在后续使用中进行显式的类型转换。
6. **异常处理**
+ 如果容器中不存在指定的 bean它会抛出 `NoSuchBeanDefinitionException`。如果在尝试创建或检索 bean 时出现其他问题,它会抛出 `BeansException`
7. **支持依赖查找**
+ 尽管 Spring 的主要目标是通过依赖注入提供依赖关系,但 `getBean` 方法提供了一种手动查找依赖的方式。
8. **初始化 Bean**
+ 如果 bean 尚未初始化(例如,对于单例 bean 在首次请求时),`getBean` 方法会触发其初始化。
### 五、最佳实践
首先来看看启动类入口,上下文环境使用`AnnotationConfigApplicationContext`此类是使用Java注解来配置Spring容器的方式构造参数我们给定了一个`MyConfiguration`组件类然后从Spring上下文中获取两个Bean对象`myServiceA``myServiceB`类型的bean。
2023-09-26 07:03:44 +00:00
```java
2023-10-24 10:02:43 +00:00
public class GetBeanApplication {
2023-09-26 07:03:44 +00:00
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
2023-10-24 10:02:43 +00:00
System.out.println("myServiceA = " + context.getBean("myServiceA"));
System.out.println("myServiceB = " + context.getBean("myServiceB"));
2023-09-26 07:03:44 +00:00
}
}
```
在配置类中,使用`@ComponentScan`注解让Spring扫描`com.xcs.spring.service`包以及其子包,由此扫描到的任何类,如果它们上面有特定的注解(如`@Component`, `@Service`, `@Repository`, `@Controller`都会被Spring自动识别并添加到容器中成为容器管理的bean。
```java
@Configuration
@ComponentScan("com.xcs.spring.service")
public class MyConfiguration {
2023-10-24 10:02:43 +00:00
2023-09-26 07:03:44 +00:00
}
```
由于我们配置中启用了`@ComponentScan`(如在`MyConfiguration`类中并指定了正确的包路径那么这两个类将被自动识别并注册到Spring容器中。
```java
package com.xcs.spring.service;
@Component
2023-10-24 10:02:43 +00:00
public class MyServiceA {
2023-09-26 07:03:44 +00:00
}
@Component
public class MyServiceB {
}
```
2023-10-24 10:02:43 +00:00
运行结果发现,这是我们自己定义的两个服务类。它们都被标记为`@Component`因此Spring容器会为每个类创建一个bean实例。
2023-09-26 07:03:44 +00:00
```java
2023-10-24 10:02:43 +00:00
myServiceA = com.xcs.spring.service.MyServiceA@23c30a20
myServiceB = com.xcs.spring.service.MyServiceB@1e1a0406
2023-09-26 07:03:44 +00:00
```
2023-10-24 10:02:43 +00:00
### 六、时序图
2023-09-26 07:03:44 +00:00
~~~mermaid
sequenceDiagram
2023-10-24 10:02:43 +00:00
DefaultListableBeanFactory->>AbstractBeanFactory:getBean(name)
note over AbstractBeanFactory: 请求一个Bean
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>AbstractBeanFactory:doGetBean(name,requiredType,args,typeCheckOnly)
note over AbstractBeanFactory: 执行实际的获取Bean逻辑
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>AbstractBeanFactory:transformedBeanName(name)
note over AbstractBeanFactory: 获取真正的bean名称
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>DefaultSingletonBeanRegistry:getSingleton(beanName)
note over DefaultSingletonBeanRegistry: 检查Bean是否为单例
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
DefaultSingletonBeanRegistry->>DefaultSingletonBeanRegistry:getSingleton(beanName,allowEarlyReference)
note over DefaultSingletonBeanRegistry: 如果允许检查早期引用的单例Bean
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
DefaultSingletonBeanRegistry->>AbstractBeanFactory:返回已注册的singleton对象
note over AbstractBeanFactory: 如果已注册则返回这个单例Bean
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>DefaultListableBeanFactory:返回Bean对象
note over DefaultListableBeanFactory: 返回到原始的请求源
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
note over AbstractBeanFactory: Bean不在缓存中需要创建
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>AbstractBeanFactory:getParentBeanFactory()
note over AbstractBeanFactory: 检查是否有父Bean工厂
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>DefaultListableBeanFactory:parentBeanFactory.getBean(name)
note over DefaultListableBeanFactory: 在父工厂中请求Bean
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>AbstractBeanFactory:markBeanAsCreated(beanName)
note over AbstractBeanFactory: 标记该Bean为已创建
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>AbstractBeanFactory:getMergedLocalBeanDefinition(beanName)
note over AbstractBeanFactory: 获取合并后的Bean定义
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>AbstractBeanFactory:checkMergedBeanDefinition(mbd, beanName, args)
note over AbstractBeanFactory: 检查合并后的Bean定义是否有效
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>AbstractBeanDefinition:getDependsOn()
note over AbstractBeanFactory: 获取该Bean的依赖
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>DefaultSingletonBeanRegistry:isDependent(beanName, dep)
note over DefaultSingletonBeanRegistry: 检查是否存在依赖
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
DefaultSingletonBeanRegistry->>DefaultSingletonBeanRegistry:isDependent(beanName, dependentBeanName, null)
note over DefaultSingletonBeanRegistry: 检查依赖
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
DefaultSingletonBeanRegistry->>DefaultSingletonBeanRegistry:canonicalName(beanName)
note over DefaultSingletonBeanRegistry: 获取Bean的规范名称
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
DefaultSingletonBeanRegistry->>AbstractBeanFactory:返回是否存在循环依赖的情况
note over AbstractBeanFactory: 返回循环依赖的检查结果
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
note over AbstractBeanFactory: 如果存在循环依赖,则抛出异常 throw new BeanCreationException(""Circular depends-on relationship between")
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>DefaultSingletonBeanRegistry:registerDependentBean(dep, beanName)
note over DefaultSingletonBeanRegistry: 注册依赖关系
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>DefaultListableBeanFactory:getBean(name)
note over DefaultListableBeanFactory: 获取被依赖的bean对象
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractBeanFactory->>DefaultSingletonBeanRegistry:getSingleton(beanName,singletonFactory)
note over DefaultSingletonBeanRegistry: 获取或创建单例Bean
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
DefaultSingletonBeanRegistry->>DefaultSingletonBeanRegistry:beforeSingletonCreation(beanName)
note over DefaultSingletonBeanRegistry: 在创建单例之前的准备工作
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
DefaultSingletonBeanRegistry->>AbstractBeanFactory:singletonFactory.getObject()
note over AbstractBeanFactory: 使用单例工厂创建Bean
AbstractBeanFactory->>AbstractAutowireCapableBeanFactory:createBean(beanName, mbd, args)
note over AbstractAutowireCapableBeanFactory: 创建新的Bean实例
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:resolveBeanClass(mbd, beanName)
note over AbstractAutowireCapableBeanFactory: 解析Bean的类
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:resolveBeforeInstantiation(beanName, mbdToUse)
note over AbstractAutowireCapableBeanFactory: 在实例化前尝试解析Bean
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:doCreateBean(beanName,mbd,args)
note over AbstractAutowireCapableBeanFactory: 执行实际的Bean创建
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:createBeanInstance(beanName, mbd, args)
note over AbstractAutowireCapableBeanFactory: 创建Bean实例
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:determineConstructorsFromBeanPostProcessors(beanClass, beanName)
note over AbstractAutowireCapableBeanFactory: 从SmartInstantiationAwareBeanPostProcessor确定构造器
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:instantiateBean(beanName, mbd)
note over AbstractAutowireCapableBeanFactory: 实例化Bean
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
note over AbstractAutowireCapableBeanFactory: 应用合并后的Bean定义后处理器
AbstractAutowireCapableBeanFactory->>DefaultSingletonBeanRegistry:addSingletonFactory(beanName,singletonFactory)
note over DefaultSingletonBeanRegistry: 添加单例工厂
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:populateBean(beanName, mbd, instanceWrapper)
note over AbstractAutowireCapableBeanFactory: 填充Bean的属性
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:postProcessAfterInstantiation(bean,beanName)
note over AbstractAutowireCapableBeanFactory: 实例化后的后处理
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:postProcessProperties(pvs,bean,beanName)
note over AbstractAutowireCapableBeanFactory: 属性后处理
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:postProcessPropertyValues(pvs,pds,bean,beanName)
note over AbstractAutowireCapableBeanFactory: 属性后处理
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:applyPropertyValues(beanName,mbd,bw,pvs)
note over AbstractAutowireCapableBeanFactory: 应用属性值
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:initializeBean(beanName, exposedObject, mbd)
note over AbstractAutowireCapableBeanFactory: 初始化Bean
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:invokeAwareMethods(beanName, bean)
note over AbstractAutowireCapableBeanFactory: 调用Aware接口方法
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
note over AbstractAutowireCapableBeanFactory: 在初始化前应用BeanPostProcessors
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:invokeInitMethods(beanName, wrappedBean, mbd)
note over AbstractAutowireCapableBeanFactory: 调用初始化方法
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
note over AbstractAutowireCapableBeanFactory: 在初始化后应用BeanPostProcessors
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:registerDisposableBeanIfNecessary(beanName, bean, mbd)
note over AbstractAutowireCapableBeanFactory: 如果需要注册可销毁的Bean
AbstractAutowireCapableBeanFactory->>AbstractBeanFactory:返回创建的单例Bean
AbstractBeanFactory->>DefaultSingletonBeanRegistry:返回创建的单例Bean
DefaultSingletonBeanRegistry->>DefaultSingletonBeanRegistry:afterSingletonCreation(beanName)
note over DefaultSingletonBeanRegistry: 单例创建后的后续处理
DefaultSingletonBeanRegistry->>DefaultSingletonBeanRegistry:addSingleton(beanName, singletonObject)
note over DefaultSingletonBeanRegistry: 向注册表中添加新的单例Bean
DefaultSingletonBeanRegistry->>AbstractBeanFactory:返回创建的单例Bean
AbstractBeanFactory->>AbstractAutowireCapableBeanFactory:getObjectForBeanInstance(sharedInstance, name, beanName, mbd)
note over AbstractAutowireCapableBeanFactory: 获取Bean实例的对象
AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:处理FactoryBean
note over AbstractAutowireCapableBeanFactory: 如果是FactoryBean则处理
AbstractAutowireCapableBeanFactory->>AbstractBeanFactory:返回真正的Bean对象
note over AbstractBeanFactory: 返回真实的Bean对象而不是FactoryBean
AbstractBeanFactory->>AbstractBeanFactory:adaptBeanInstance(name, beanInstance, requiredType)
note over AbstractBeanFactory: 适配Bean实例的类型
AbstractBeanFactory->>DefaultListableBeanFactory:返回真正的Bean对象
note over DefaultListableBeanFactory: 返回到原始的请求源
~~~
### 七、源码分析
在`org.springframework.beans.factory.support.AbstractBeanFactory#getBean(name)`方法中,这个方法内部调用了`doGetBean`,并且传递了四个参数。
2023-09-26 07:03:44 +00:00
```java
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
```
2023-10-24 10:02:43 +00:00
在`org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean`方法中是Spring框架中`AbstractBeanFactory`类的核心方法用于获取bean实例。它考虑了单例、原型、特定作用域bean的创建还处理了bean定义、循环引用、依赖等各种情况。
2023-09-26 07:03:44 +00:00
```java
protected <T> T doGetBean(
2023-10-24 10:02:43 +00:00
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// 步骤1: 转换bean名称
2023-09-26 07:03:44 +00:00
String beanName = transformedBeanName(name);
2023-10-24 10:02:43 +00:00
// 步骤2: 尝试从缓存中检索单例bean
2023-09-26 07:03:44 +00:00
Object sharedInstance = getSingleton(beanName);
2023-10-24 10:02:43 +00:00
Object beanInstance;
2023-09-26 07:03:44 +00:00
if (sharedInstance != null && args == null) {
2023-10-24 10:02:43 +00:00
// 获取bean实例本身
2023-09-26 07:03:44 +00:00
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
2023-10-24 10:02:43 +00:00
// 步骤3: 处理原型作用域的bean并检查是否已在创建中
2023-09-26 07:03:44 +00:00
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
2023-10-24 10:02:43 +00:00
// 步骤4: 尝试在父Bean工厂中检索bean定义
2023-09-26 07:03:44 +00:00
BeanFactory parentBeanFactory = getParentBeanFactory();
2023-10-24 10:02:43 +00:00
2023-09-26 07:03:44 +00:00
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
2023-10-24 10:02:43 +00:00
String nameToLookup = originalBeanName(name);
2023-09-26 07:03:44 +00:00
// ... [代码部分省略以简化]
2023-10-24 10:02:43 +00:00
return (T) parentBeanFactory.getBean(nameToLookup);
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// 步骤5: 标记bean为已创建状态
2023-09-26 07:03:44 +00:00
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
2023-10-24 10:02:43 +00:00
// 步骤6: 获取合并后的bean定义
2023-09-26 07:03:44 +00:00
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
2023-10-24 10:02:43 +00:00
// 步骤7: 确保bean的依赖已经初始化
2023-09-26 07:03:44 +00:00
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
2023-10-24 10:02:43 +00:00
for (String dep : dependsOn) {
// 步骤7.1: 是否存在循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 步骤7.2: 注册Bean与Bean之间的依赖关系
registerDependentBean(dep, beanName);
// 步骤7.3: 获取被依赖的Bean对象
getBean(dep);
}
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// 步骤8: 根据bean的作用域创建或检索bean实例
2023-09-26 07:03:44 +00:00
if (mbd.isSingleton()) {
2023-10-24 10:02:43 +00:00
// 步骤8.1: 处理单例作用域
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// ... [代码部分省略以简化]
}
});
// 步骤8.2: 获取bean实例本身
2023-09-26 07:03:44 +00:00
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
2023-10-24 10:02:43 +00:00
// 处理原型作用域
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
}
else {
2023-10-24 10:02:43 +00:00
// 处理其他作用域
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
}
}
catch (BeansException ex) {
2023-10-24 10:02:43 +00:00
// 处理bean创建失败的情况
// ... [代码部分省略以简化]
}
finally {
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
}
}
2023-10-24 10:02:43 +00:00
// 步骤9: 适配bean实例
2023-09-26 07:03:44 +00:00
return adaptBeanInstance(name, beanInstance, requiredType);
}
```
2023-10-24 10:02:43 +00:00
首先来到在`org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean`方法中的步骤1。在`org.springframework.beans.factory.support.AbstractBeanFactory#transformedBeanName`方法中主要是用来转换bean名称的。Spring允许在引用bean时使用特定的前缀例如`&`前缀用于表示一个bean是`FactoryBean`,这样我们可以通过`&beanName`来获取`FactoryBean`对象本身,而不是它生产的对象。
```java
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
```
在`org.springframework.core.SimpleAliasRegistry#canonicalName`方法中主要是用来获取bean的规范名称的。在Spring中bean可以有多个别名这个方法的目的是从别名链中找到最终的规范名称。
```java
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
```
然后来到在`org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean`方法中的步骤2。在`org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(beanName)`方法中,又调用了另外一个重载版本,还接受一个`boolean`参数表示当bean正在被创建但尚未完成时是否允许提前暴露这个bean的引用。传递`true`作为这个参数意味着是允许的。
2023-09-26 07:03:44 +00:00
```java
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
```
2023-10-24 10:02:43 +00:00
在`org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(beanName,allowEarlyReference)`方法中首先它从单例缓存中尝试获取bean。如果bean正在创建中方法会从提前暴露的缓存中获取它以处理循环引用。为确保线程安全性在同步块内进行进一步的检查和bean的创建。如果bean仍未被创建但存在一个工厂那么它会用这个工厂创建bean。最后方法返回找到或新创建的bean或者在没有找到bean时返回`null`。
2023-09-26 07:03:44 +00:00
```java
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
2023-10-24 10:02:43 +00:00
// 1. 从已完成的单例缓存中初步检查bean
2023-09-26 07:03:44 +00:00
Object singletonObject = this.singletonObjects.get(beanName);
2023-10-24 10:02:43 +00:00
// 2. 检查bean是否正在创建中以处理可能的循环引用
2023-09-26 07:03:44 +00:00
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
2023-10-24 10:02:43 +00:00
// 3. 尝试从提前暴露的单例缓存中获取bean
2023-09-26 07:03:44 +00:00
singletonObject = this.earlySingletonObjects.get(beanName);
2023-10-24 10:02:43 +00:00
// 4. 如果仍然没有获取到bean且允许提前引用则进一步处理
2023-09-26 07:03:44 +00:00
if (singletonObject == null && allowEarlyReference) {
2023-10-24 10:02:43 +00:00
// 5. 为了确保线程安全,使用同步块
2023-09-26 07:03:44 +00:00
synchronized (this.singletonObjects) {
2023-10-24 10:02:43 +00:00
// 6. 在同步块内再次检查缓存,以确保线程安全
2023-09-26 07:03:44 +00:00
singletonObject = this.singletonObjects.get(beanName);
2023-10-24 10:02:43 +00:00
2023-09-26 07:03:44 +00:00
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
2023-10-24 10:02:43 +00:00
// 7. 如果仍然没有找到尝试使用singletonFactory创建bean
2023-09-26 07:03:44 +00:00
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
2023-10-24 10:02:43 +00:00
// 8. 使用singletonFactory创建bean
2023-09-26 07:03:44 +00:00
singletonObject = singletonFactory.getObject();
2023-10-24 10:02:43 +00:00
// 9. 将新创建的bean添加到提前暴露的单例缓存中
2023-09-26 07:03:44 +00:00
this.earlySingletonObjects.put(beanName, singletonObject);
2023-10-24 10:02:43 +00:00
// 10. 从singletonFactories缓存中移除beanName因为它已经被使用
2023-09-26 07:03:44 +00:00
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
2023-10-24 10:02:43 +00:00
// 11. 返回找到或创建的单例bean
2023-09-26 07:03:44 +00:00
return singletonObject;
}
```
2023-10-24 10:02:43 +00:00
然后来到在`org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean`方法中的步骤3。在`org.springframework.beans.factory.support.AbstractBeanFactory#isPrototypeCurrentlyInCreation`方法中用于确定指定名称的原型bean是否当前正在创建中。
2023-09-26 07:03:44 +00:00
```java
2023-10-24 10:02:43 +00:00
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
```
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
然后来到在`org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean`方法中的步骤5。在`org.springframework.beans.factory.support.AbstractBeanFactory#markBeanAsCreated`方法中主要目的是标记指定的bean已经被创建或正在被创建。它在Spring的bean生命周期中起到关键作用特别是当需要确保bean只被创建一次或者对其进行某些状态检查时。
```java
protected void markBeanAsCreated(String beanName) {
// 1. 初步检查bean是否已被标记为已创建
if (!this.alreadyCreated.contains(beanName)) {
// 2. 为了确保在多线程环境下的线程安全,进行同步操作
synchronized (this.mergedBeanDefinitions) {
// 3. 双重检查锁定模式再次确认bean是否已被标记为已创建
if (!this.alreadyCreated.contains(beanName)) {
// 4. 清除bean的合并定义以便在后续访问时重新合并
clearMergedBeanDefinition(beanName);
// 5. 在集合中标记bean已被创建
this.alreadyCreated.add(beanName);
}
2023-09-26 07:03:44 +00:00
}
}
2023-10-24 10:02:43 +00:00
}
```
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
然后来到在`org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean`方法中的步骤6。在`org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition`方法中主要是用于获取给定bean名称的合并bean定义。合并的bean定义是从父bean和子bean如果有的话定义中合并的结果。
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
```java
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// 1. 快速从并发映射中检查bean定义这样做可以最小化锁定。
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
// 2. 如果合并的bean定义存在并且没有过期直接返回它。
if (mbd != null && !mbd.stale) {
return mbd;
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// 3. 如果上述检查失败进一步获取并返回合并的bean定义。
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
```
在`org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanDefinition`方法中主要用于查找bean定义。
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
```java
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
// 1. 从beanDefinitionMap中获取bean的定义
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
// 2. 如果没有找到BeanDefinition进行日志跟踪并抛出异常
if (bd == null) {
// 如果启用了trace级别的日志记录一条日志
if (logger.isTraceEnabled()) {
logger.trace("No bean named '" + beanName + "' found in " + this);
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// 抛出没有找到BeanDefinition的异常
throw new NoSuchBeanDefinitionException(beanName);
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// 3. 返回找到的BeanDefinition
return bd;
}
```
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
在`org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(beanName, bd)`方法中,我们传递了`null`作为父bean定义表示不需要合并父bean定义。
```java
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
2023-09-26 07:03:44 +00:00
}
```
2023-10-24 10:02:43 +00:00
在`org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(beanName,bd,containingBd)`方法中主要目的是获取指定bean名称的合并bean定义。它的主要工作是处理bean定义的父子关系和其他相关设置然后返回一个合并后的bean定义。
2023-09-26 07:03:44 +00:00
```java
2023-10-24 10:02:43 +00:00
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// 1. 对mergedBeanDefinitions进行同步以确保线程安全。
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// 2. 在完整的锁定中检查,以确保使用相同的合并实例。
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// 3. 如果bean定义未被合并或已过期进行合并操作。
if (mbd == null || mbd.stale) {
previous = mbd;
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// 4. 处理没有父定义的情况。
if (bd.getParentName() == null) {
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// 5. 处理有父定义的情况:需要与父定义合并。
else {
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
// ... [代码部分省略以简化]
}
}
}
catch (NoSuchBeanDefinitionException ex) {
// ... [代码部分省略以简化]
}
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// 6. 如果bean定义的范围没有明确设置将其默认为单例。
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// 7. 非单例bean中的bean不能是单例。在这里修复这种情况。
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// 8. 如果需要缓存合并后的bean定义。
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
}
// 9. 如果之前存在一个bean定义复制相关的缓存。
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
// 10. 返回合并后的bean定义。
return mbd;
}
}
```
然后来到在`org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean`方法中的步骤7.1。Spring处理了`@DependsOn`注解。这个注解允许开发者定义bean初始化之间的依赖关系确保一个bean在另一个bean之前被初始化和销毁。为了深入了解`@DependsOn`注解的工作机制及其在Spring中的实现您可以查阅已经准备好的专门分析该注解的博客文章。
[@DependsOn注解详解](https://github.com/xuchengsheng/spring-reading/blob/master/spring-annotation/spring-annotation-dependsOn)
```java
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 步骤7.1: 是否存在循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 步骤7.2: 注册Bean与Bean之间的依赖关系
registerDependentBean(dep, beanName);
// 步骤7.3: 获取被依赖的Bean对象
getBean(dep);
}
}
```
然后来到在`org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean`方法中的步骤8.1。在`org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(beanName, singletonFactory)`方法中首先尝试从缓存中检索该bean。如果没有找到它会使用提供的`singletonFactory`来创建这个bean并在创建过程中进行前置和后置处理以确保处理诸如循环引用等问题。创建的bean会被添加到缓存中。此外该方法还处理了在创建过程中可能出现的各种异常并确保在多线程环境中的线程安全。最后返回所需的单例bean。
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
```java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 首先尝试从缓存中获取单例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// ... [代码部分省略以简化]
// 前置处理例如标记这个bean正在创建以处理循环引用等问题。
beforeSingletonCreation(beanName);
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
try {
2023-10-24 10:02:43 +00:00
// 使用singletonFactory创建单例对象
2023-09-26 07:03:44 +00:00
singletonObject = singletonFactory.getObject();
newSingleton = true;
2023-10-24 10:02:43 +00:00
}
2023-09-26 07:03:44 +00:00
catch (IllegalStateException ex) {
// ... [代码部分省略以简化]
2023-10-24 10:02:43 +00:00
}
2023-09-26 07:03:44 +00:00
catch (BeanCreationException ex) {
// ... [代码部分省略以简化]
2023-10-24 10:02:43 +00:00
}
2023-09-26 07:03:44 +00:00
finally {
// ... [代码部分省略以简化]
afterSingletonCreation(beanName);
}
2023-10-24 10:02:43 +00:00
// 如果成功创建了新的单例bean将其添加到缓存中
2023-09-26 07:03:44 +00:00
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
2023-10-24 10:02:43 +00:00
// 返回现有或新创建的单例bean
2023-09-26 07:03:44 +00:00
return singletonObject;
}
}
```
2023-10-24 10:02:43 +00:00
在`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(beanName,mbd,args)`方法中首先尝试进行前置处理可能返回一个由BeanPostProcessors提供的代理bean。如果没有代理bean它会进行真正的bean创建。
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
`resolveBeforeInstantiation` 方法主要在实际的 bean 实例化之前尝试解析 bean。这允许`InstantiationAwareBeanPostProcessor`在 bean 的实际实例化过程开始之前对其进行操作。
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
在Spring中`InstantiationAwareBeanPostProcessor` 是一个特殊类型的`BeanPostProcessor`它提供了更多的回调方法特别是允许在实例化bean之前以及属性填充之前对bean进行处理。例如它可以在 bean 实例化之前返回一个代理对象,从而避免默认的 bean 实例化过程。
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
要深入了解这两个接口以及它们在 Spring 框架中的工作方式,您可以参考以下两篇博客文章:
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
1. [InstantiationAwareBeanPostProcessor 接口详解](https://github.com/xuchengsheng/spring-reading/blob/master/spring-interface/spring-interface-instantiationAwareBeanPostProcessor)
2. [BeanPostProcessor 接口详解](https://github.com/xuchengsheng/spring-reading/blob/master/spring-interface/spring-interface-beanPostProcessor)
2023-09-26 07:03:44 +00:00
```java
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
2023-10-24 10:02:43 +00:00
throws BeanCreationException {
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
RootBeanDefinition mbdToUse = mbd;
2023-10-24 10:02:43 +00:00
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
try {
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
// ... [代码部分省略以简化]
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
2023-10-24 10:02:43 +00:00
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// ... [代码部分省略以简化]
}
catch (Throwable ex) {
// ... [代码部分省略以简化]
}
}
```
2023-10-24 10:02:43 +00:00
在`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean`方法中主要处理了bean生命周期中的多个关键阶段从bean的实例化、属性注入、初始化到bean的清理注册。
2023-09-26 07:03:44 +00:00
```java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
2023-10-24 10:02:43 +00:00
// Step 1: 尝试实例化bean
2023-09-26 07:03:44 +00:00
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
2023-10-24 10:02:43 +00:00
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// Step 2: 合并bean定义的后置处理
2023-09-26 07:03:44 +00:00
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
// ... [代码部分省略以简化]
}
mbd.postProcessed = true;
}
}
2023-10-24 10:02:43 +00:00
// Step 3: 处理可能的循环引用通过提前暴露bean的引用
2023-09-26 07:03:44 +00:00
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
2023-10-24 10:02:43 +00:00
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
2023-10-24 10:02:43 +00:00
// Step 4: 初始化bean实例填充bean属性并应用后处理器
2023-09-26 07:03:44 +00:00
Object exposedObject = bean;
try {
2023-10-24 10:02:43 +00:00
// 属性填充
2023-09-26 07:03:44 +00:00
populateBean(beanName, mbd, instanceWrapper);
2023-10-24 10:02:43 +00:00
// 初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
2023-09-26 07:03:44 +00:00
} catch (Throwable ex) {
// ... [代码部分省略以简化]
}
2023-10-24 10:02:43 +00:00
// Step 5: 如果需要注册bean以便在容器关闭时进行清理
2023-09-26 07:03:44 +00:00
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
// ... [代码部分省略以简化]
}
return exposedObject;
}
```
2023-10-24 10:02:43 +00:00
在`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance`方法中,首先尝试从后处理器获取构造函数,然后检查是否有首选构造函数,最后如果没有其他选项,它会使用无参数构造函数。
2023-09-26 07:03:44 +00:00
```java
2023-10-24 10:02:43 +00:00
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... [代码部分省略以简化]
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
// Step 1: 首先尝试从BeanPostProcessors确定构造函数这主要是为了处理例如@Autowired注解的情况
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 如果确定了构造函数或者bean定义中有相关的自动装配模式和构造函数参数则使用自动装配构造函数创建bean实例
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// Step 2: 如果BeanDefinition中存在首选构造函数使用这些构造函数
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
2023-09-26 07:03:44 +00:00
}
2023-10-24 10:02:43 +00:00
// Step 3: 如果前面的步骤都没有返回bean实例那么使用无参数构造函数实例化bean
return instantiateBean(beanName, mbd);
2023-09-26 07:03:44 +00:00
}
```
2023-10-24 10:02:43 +00:00
在`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors`方法中,在`determineConstructorsFromBeanPostProcessors`方法中Spring查询所有注册的`SmartInstantiationAwareBeanPostProcessor`来确定bean的构造函数。这允许开发者或Spring内部组件对bean的实例化过程有更大的控制权。特别地`SmartInstantiationAwareBeanPostProcessor`接口扩展了Spring的标准`BeanPostProcessor`为bean的实例化提供更为智能的预测和干预能力。例如它可以在bean实例化之前尝试猜测最合适的构造函数或者提供代理类来代替实际的bean实例。对于想要深入了解`SmartInstantiationAwareBeanPostProcessor`的工作原理和如何使用它的开发者来说,我推荐阅读这篇详细的博客[SmartInstantiationAwareBeanPostProcessor源码分析](https://github.com/xuchengsheng/spring-reading/blob/master/spring-interface/spring-interface-smartInstantiationAwareBeanPostProcessor)。在这篇博客中您将获得关于该接口及其与Spring框架交互的详尽解释。
2023-09-26 07:03:44 +00:00
```java
2023-10-24 10:02:43 +00:00
@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
2023-09-26 07:03:44 +00:00
throws BeansException {
2023-10-24 10:02:43 +00:00
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
2023-09-26 07:03:44 +00:00
}
}
2023-10-24 10:02:43 +00:00
return null;
2023-09-26 07:03:44 +00:00
}
```
2023-10-24 10:02:43 +00:00
### 八、注意事项
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
### 九、总结
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
#### 最佳实践总结
2023-09-26 07:03:44 +00:00
2023-10-24 10:02:43 +00:00
#### 源码分析总结