乐于分享
好东西不私藏

Spring 源码分析(五):类管理容器的设计

Spring 源码分析(五):类管理容器的设计
上一篇介绍了 ApplicationContext(上下文)的设计,它是 Spring 应用运行时的统一环境入口,聚合了 Bean 管理、资源访问、事件发布、国际化等六项能力,其中 Bean 管理能力是最核心的功能,本篇重点对该部分进行分析。
ApplicationContext 接口的第一个通用实现类为 GenericApplicationContext,ApplicationContext 本身并不亲自实现 Bean 管理能力,而是将它们委托给一个专职对象:DefaultListableBeanFactory。这个对象,就是本篇所说的容器。为了方便理解,我们将 ApplicationContext 类图进行简化,删除所有接口类继承信息,仅保留类继承关系(如图1):
图1 GenericApplicationContext 类层次结构
1. BeanFactory:容器的接口体系
1.1 BeanFactory 与 ApplicationContext 的关系
BeanFactory 接口是什么?他和 ApplicationContext 接口是什么关系?搞清楚这两个概念是理解容器设计的前提。
BeanFactory 是 Spring IoC 容器的根接口,它的职责只有一件事:按需提供 Bean。接口定义极为精简,核心方法就是各种形式的 getBean:
// BeanFactory.javapublic interface BeanFactory {    // 按名称获取 Bean    Object getBean(String name) throws BeansException;    // 按名称和类型获取 Bean    <T> T getBean(String name, Class<T> requiredType) throws BeansException;    // 按类型获取 Bean    <T> T getBean(Class<T> requiredType) throws BeansException;    // 查询是否包含某个 Bean    boolean containsBean(String name);    // 查询是否是单例    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;    // 查询是否是原型    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;    // 获取 Bean 的类型    Class<?> getType(String name) throws NoSuchBeanDefinitionException;}
ApplicationContext 通过接口继承将 BeanFactory 的能力纳入自身,使得调用方可以直接向 ApplicationContext 发起 getBean 请求,而无需关心底层是哪个对象在处理。但是在具体实现中,接口继承只是"宣称"了接口,真正的实现发生在 GenericApplicationContext 这一层:
// GenericApplicationContext.javapublic class GenericApplicationContext extends AbstractApplicationContext        implements BeanDefinitionRegistry {    private final DefaultListableBeanFactory beanFactory; // ← 持有容器实例    public GenericApplicationContext() {        this.beanFactory = new DefaultListableBeanFactory(); // ← 构造时创建    }    @Override    public final ConfigurableListableBeanFactory getBeanFactory() {        return this.beanFactory; // ← 暴露给外部    }    // 所有 BeanFactory 相关的方法,全部委托给 this.beanFactory    @Override    public <T> T getBean(Class<T> requiredType) throws BeansException {        return getBeanFactory().getBean(requiredType);    }    // ...}
实际设计中遵循了组合优于继承(Composition over Inheritance)的原则:ApplicationContext 没有直接继承 DefaultListableBeanFactory 的实现,而是持有它的实例,将调用转发给它。这样做的好处是两者的关注点完全分离——上下文负责生命周期编排,容器负责 Bean 的注册与管理,互不干扰。
1.2 BeanFactory 接口的层次结构
BeanFactory 根接口之上,Spring 通过接口扩展构建了一棵分层清晰的能力树:
BeanFactory                            ← 根接口:按需提供 Bean  ├── HierarchicalBeanFactory          ← 扩展:支持父子容器结构  ├── ListableBeanFactory              ← 扩展:支持按类型批量查询 Bean  └── AutowireCapableBeanFactory       ← 扩展:支持自动装配(为外部对象注入依赖)        └── ConfigurableBeanFactory    ← 可配置:设置类加载器、Bean 后置处理器等              └── ConfigurableListableBeanFactory  ← 综合以上全部能力的"全功能"接口                    └── DefaultListableBeanFactory (唯一核心实现类)
每个接口的扩展点都有明确的设计意图:
接口
扩展能力
典型方法
ListableBeanFactory
批量查询
getBeansOfType(Class<T>)getBeanNamesForType(Class<?>)
HierarchicalBeanFactory
父子容器
getParentBeanFactory(),子容器找不到 Bean   时向父容器委托
AutowireCapableBeanFactory
外部注入
autowireBean(Object),为非 Spring   管理的对象执行依赖注入
ConfigurableBeanFactory
容器配置
setBeanClassLoader()addBeanPostProcessor()
ConfigurableListableBeanFactory
冻结与预实例化
freezeConfiguration()preInstantiateSingletons()
图2 DefaultListableBeanFactory 接口与类层次结构
DefaultListableBeanFactory 站在这棵树的叶节点,实现了上述所有接口,是 Spring 中唯一一个完整实现了 IoC 容器全部能力的类。整个 Spring Framework 运行时使用的容器,几乎都是 DefaultListableBeanFactory 的实例。
1.3 BeanDefinitionRegistry:容器的另一张面孔
除了 BeanFactory 体系,DefaultListableBeanFactory 还实现了另一个重要接口——BeanDefinitionRegistry:
public interface BeanDefinitionRegistry extends AliasRegistry {    // 注册一个 Bean 定义    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)            throws BeanDefinitionStoreException;    // 移除一个 Bean 定义    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;    // 获取一个 Bean 定义    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;    // 是否包含某个 Bean 定义    boolean containsBeanDefinition(String beanName);    // 获取所有已注册的 Bean 名称    String[] getBeanDefinitionNames();}
这揭示了容器的双重身份:它既是消费者(BeanFactory:按需提供 Bean 实例),也是注册表(BeanDefinitionRegistry:接收并存储 Bean 的元数据描述)。Bean 的注册与 Bean 的获取,在同一个对象上完成,将"定义管理"与"实例管理"统一在容器内部,让容器真正成为 Bean 生命周期的全权负责人。
2. DefaultListableBeanFactory:核心实现解析
2.1 类的继承体系
DefaultListableBeanFactory 的继承树展示了 Spring 是如何通过多层抽象类拆分容器的实现复杂度的:
DefaultSingletonBeanRegistry        ← 单例注册表:三级缓存、singleton 生命周期  └── AbstractBeanFactory           ← 模板基类:getBean / doGetBean 的骨架逻辑        └── AbstractAutowireCapableBeanFactory  ← 自动装配:createBean / populateBean              └── DefaultListableBeanFactory    ← 全功能容器:Bean 定义注册与批量查询
每一层抽象都承担着独立的职责:
抽象类
核心职责
DefaultSingletonBeanRegistry
管理单例 Bean 的三级缓存,处理循环依赖
AbstractBeanFactory
定义 getBean 的核心骨架,处理 scope、别名、类型转换
AbstractAutowireCapableBeanFactory
实现 Bean 的实例化、属性填充(populateBean)、初始化回调
DefaultListableBeanFactory
实现 BeanDefinitionRegistry,提供 Bean 定义的增删查,以及按类型批量查询
2.2 核心数据结构
DefaultListableBeanFactory 内部维护着多张 Map,分工明确,共同支撑 Bean 生命周期管理的全过程:
// DefaultListableBeanFactory.java// ── Bean 定义注册表 ──// Bean名称 → BeanDefinition(Bean的元数据描述,类名、scope、依赖等)private final Map<StringBeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);// 已注册的 Bean 名称列表(ArrayList保证注册顺序)private volatile List<String> beanDefinitionNames = new ArrayList<>(256);// 类型 → Bean名称列表(类型查询的反向索引)private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);// ── 单例实例缓存(继承自 DefaultSingletonBeanRegistry)──// 一级缓存:完全初始化的单例对象(name → bean instance)private final Map<StringObject> singletonObjects = new ConcurrentHashMap<>(256);// 二级缓存:早期暴露的原始对象(已实例化但未完成属性注入,用于打破循环依赖)private final Map<StringObject> earlySingletonObjects = new ConcurrentHashMap<>(16);// 三级缓存:单例工厂(ObjectFactory,用于生成早期引用,支持 AOP 代理的提前暴露)private final Map<StringObjectFactory<?>> singletonFactories = new HashMap<>(16);
这些数据结构的设计体现了容器的核心关切:beanDefinitionMap 是容器的"设计图纸库",在 Bean 被实际实例化之前,所有的 Bean 元数据都存储在这里;singletonObjects 是容器的"成品仓库",完成初始化的单例 Bean 存放于此,后续每次 getBean 都直接从这里取,确保整个应用生命周期内只存在一个实例。
2.3 三级缓存与循环依赖
三级缓存的设计源于 Spring 需要解决一个棘手问题:循环依赖(Circular Dependency)。考虑以下场景:
Bean A 依赖 Bean BBean B 依赖 Bean A
若没有特殊处理,getBean(A) 会触发 createBean(A) → 发现需要 B → createBean(B) → 发现需要 A → createBean(A) → 无限递归。
Spring 的解法是提前暴露:在 Bean 的属性填充完成之前,先将它的"半成品引用"(或生成它的工厂)放入三级缓存,使后续对该 Bean 的依赖请求能够提前拿到引用,从而打破循环:
①  createBean(A) 开始②  实例化 A(仅 new,未注入属性)③  将 A 的 ObjectFactory 放入三级缓存 singletonFactories④  填充属性:发现需要 B → getBean(B)⑤    createBean(B) 开始⑥    实例化 B⑦    将 B 的 ObjectFactory 放入三级缓存⑧    填充属性:发现需要 A → getBean(A)⑨      getSingleton(A):一级无 → 二级无 → 三级命中!⑩      从三级缓存的 ObjectFactory 获取 A 的早期引用⑪      将早期引用放入二级缓存,移除三级缓存⑫    B 拿到 A 的早期引用,完成属性注入 → B 初始化完成 → 进入一级缓存⑬  A 拿到完整的 B,完成属性注入 → A 初始化完成 → 进入一级缓存
三级缓存中存放的是 ObjectFactory 而非直接存放早期引用,这是为了支持 AOP:当 A 被 AOP 代理时,暴露给外部的应该是代理对象,而非原始对象。ObjectFactory 在被调用时会触发 SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference(),使 AOP 有机会在循环依赖场景中也能正确地返回代理对象,而不是原始裸对象。
需要注意的是,Spring 的三级缓存只解决属性注入(setter/field)引发的循环依赖,无法解决构造函数注入的循环依赖——因为构造函数注入发生在实例化阶段,此时尚未执行第③步,早期引用还不存在。
💡思考:
关于无法解决构造函数注入的循环依赖这个问题,有开发经验的同志们可能会有点疑惑,因为在 Spring 官方文档和社区的推荐实践中,都是优先推荐构造函数注入模式,相较于属性注入模式有2个优点:一是能够更加清晰揭示对象之间的依赖关系;二是更有利于通过 Mock 方式进行单元测试。那么由此引发了两个问题:一是构造函数注入模式中的循环依赖如何处理;二是如果真的不支持循环依赖,那么像双向链表这样的数据结构如何建立呢。 
对于第1个问题,在 Spring 官网中给出的解决方案是使用属性注入模式来解决循环依赖的问题(One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.),但是从文中的态度可以看出,循环依赖不被认为是一种好的设计,他会增加对象之间的耦合,从框架或运行程序设计的角度,更倾向于使用类似协调者这类层次清晰的设计模式来规避这种问题。 那么第二个问题随之而来,如果 Spring 不推荐循环依赖的设计方式,类似双向链表这样的数据结构如何实现呢。这里其实要从 Spring 容器管理的主要目标来看,虽然 Spring 容器支持对单例(Singleton)和原型(prototype)的实例管理,但主要管理的是程序的服务和组件,而不是数据。换句话说,单例(在方法区中创建的全局唯一的实例)是 Spring 容器管理的核心,而对于可变的,用来表达业务模型和供具体算法操作的数据结构,则应在由开发人员自行管理,例如使用线程安全的容器类(如 ConcurrentHashMap)、使用线程局部变量(ThreadLocal)来存储和管理数据,以及可变的、用于承载业务的值对象、索引结构等。
3. BeanDefinition:Bean 的蓝图
3.1 什么是 BeanDefinition
在 Spring 中,Bean 的实例化并非在配置被读取时立即发生,而是分为两个完全独立的阶段:
1.注册阶段:扫描配置(注解、XML 等),将 Bean 的元数据封装为 BeanDefinition 对象,存入容器的 beanDefinitionMap。此阶段不创建任何 Bean 实例。
2.实例化阶段:容器根据 beanDefinitionMap 中存储的 BeanDefinition,按需(或在 refresh() 尾声统一)创建 Bean 实例。
BeanDefinition 是连接这两个阶段的桥梁,它是 Bean 的元数据描述,记录了"如何创建这个 Bean"的全部信息:
// BeanDefinition.java(接口)public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; // "singleton"    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; // "prototype"    // Bean 的全限定类名(如 "com.example.UserService")    void setBeanClassName(@Nullable String beanClassName);    String getBeanClassName();    // scope:singleton / prototype / request / session ...    void setScope(@Nullable String scope);    String getScope();    // 是否懒加载(@Lazy)    void setLazyInit(boolean lazyInit);    boolean isLazyInit();    // depends-on:指定必须在本 Bean 之前初始化的 Bean 名称    void setDependsOn(@Nullable String... dependsOn);    String[] getDependsOn();    // 是否是自动注入的候选者(@Primary / @Qualifier 会影响此项)    void setAutowireCandidate(boolean autowireCandidate);    boolean isAutowireCandidate();    // 是否是首选候选者(@Primary)    void setPrimary(boolean primary);    boolean isPrimary();    // 工厂 Bean 名称和工厂方法名(对应 @Bean 方法的宿主类和方法名)    void setFactoryBeanName(@Nullable String factoryBeanName);    void setFactoryMethodName(@Nullable String factoryMethodName);    // 构造函数参数值和属性值    ConstructorArgumentValues getConstructorArgumentValues();    MutablePropertyValues getPropertyValues();    // 初始化和销毁回调方法名(对应 @PostConstruct / @PreDestroy 或 XML 配置)    void setInitMethodName(@Nullable String initMethodName);    void setDestroyMethodName(@Nullable String destroyMethodName);}
3.2 BeanDefinition 的实现层次
BeanDefinition 接口同样有一棵清晰的实现树:
AbstractBeanDefinition          ← 抽象基类:持有所有公共属性字段  ├── RootBeanDefinition        ← 合并后的"最终"定义(容器内部使用)  ├── ChildBeanDefinition       ← 子定义(继承父定义的属性,已较少使用)  └── GenericBeanDefinition     ← 通用定义:@Component / @Bean 注解扫描时默认产生        └── ScannedGenericBeanDefinition  ← 由类路径扫描产生(携带 AnnotationMetadata)        └── AnnotatedGenericBeanDefinition ← 由显式注册产生(如主配置类)
在现代 Spring Boot 应用中,绝大多数 BeanDefinition 都是 ScannedGenericBeanDefinition(来自组件扫描)或 ConfigurationClassBeanDefinition(来自 @Bean 方法解析),它们都携带了丰富的注解元数据(AnnotationMetadata),供后续处理器使用。
3.3 注册机制:BeanDefinitionRegistry
Bean 定义的注册统一通过 BeanDefinitionRegistry.registerBeanDefinition() 完成,其核心实现在 DefaultListableBeanFactory 中:
// DefaultListableBeanFactory.java@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)        throws BeanDefinitionStoreException {    // 1. 校验参数合法性    Assert.hasText(beanName, "Bean name must not be empty");    Assert.notNull(beanDefinition, "BeanDefinition must not be null");    // 2. 如果已存在同名定义,检查是否允许覆盖    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);    if (existingDefinition != null) {        if (!isAllowBeanDefinitionOverriding()) {            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);        }        // 允许覆盖则直接更新 Map,不修改 beanDefinitionNames 顺序        this.beanDefinitionMap.put(beanName, beanDefinition);    } else {        // 3. 新 Bean:先写 Map,再追加到有序 List        this.beanDefinitionMap.put(beanName, beanDefinition);        List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);        updatedDefinitions.addAll(this.beanDefinitionNames);        updatedDefinitions.add(beanName);        this.beanDefinitionNames = updatedDefinitions; // volatile 写,保证可见性    }    // 4. 清空类型缓存(新 Bean 定义可能影响按类型查询的结果)    clearByTypeCache();}
注意 beanDefinitionNames 使用 volatile + 整体替换(Copy-on-Write 风格)而非直接修改,这保证了在容器初始化期间多线程读取 beanDefinitionNames 时始终能看到完整、一致的视图,避免了对 ArrayList 加锁带来的性能开销。
4. 容器的初始化:prepareContext
在上一篇文章中,我们看到 SpringApplication.run() 通过 createApplicationContext() 创建了 Context 实例(同时内部自动创建了 DefaultListableBeanFactory)。接下来执行的是 prepareContext(),它负责在正式刷新之前,为容器准备好初始状态:
// SpringApplication.javaprivate void prepareContext(DefaultBootstrapContext bootstrapContext,        ConfigurableApplicationContext context,        ConfigurableEnvironment environment,        SpringApplicationRunListeners listeners,        ApplicationArguments applicationArguments,        Banner printedBanner) {    // 1. 将 Environment 绑定到 Context    context.setEnvironment(environment);    // 2. 对 Context 进行后置处理(如设置 BeanNameGenerator、ResourceLoader 等)    postProcessApplicationContext(context);    // 3. 依次执行所有 ApplicationContextInitializer    applyInitializers(context);    // 4. 广播"Context 已准备完成"事件    listeners.contextPrepared(context);    // 5. 关闭 BootstrapContext,将其中的 Bean 迁移到主 Context    bootstrapContext.close(context);    // 6. 将主配置类(@SpringBootApplication 标注的类)注册为 BeanDefinition    Set<Object> sources = getAllSources();    load(context, sources.toArray());         // ← 核心步骤    // 7. 广播"Context 已加载完成"事件    listeners.contextLoaded(context);}
4.1 主配置类的注册:load()
load() 方法内部委托给 BeanDefinitionLoader,它能够识别多种形式的配置来源(Class、Package、XML 等),并将其统一转换为 BeanDefinition 注册进容器:
// BeanDefinitionLoader.javaint load() {    int count = 0;    for (Object source : this.sources) {        count += load(source); // 对每个 source 分发处理    }    return count;}private int load(Object source) {    Assert.notNull(source, "Source must not be null");    if (source instanceof Class<?> clazz) {        return load(clazz); // 注解配置类(最常见)    }    if (source instanceof Resource resource) {        return load(resource); // XML 配置文件    }    if (source instanceof Package pkg) {        return load(pkg); // 包路径扫描    }    if (source instanceof CharSequence) {        return load((CharSequence) source); // 字符串(尝试按类名/包名/资源路径解析)    }    throw new IllegalArgumentException("Invalid source type " + source.getClass());}
对于 @SpringBootApplication 标注的主配置类,走 load(Class<?> source) 分支,最终调用 AnnotatedBeanDefinitionReader.register(),将主配置类注册为 AnnotatedGenericBeanDefinition 存入容器。
此时,容器的 beanDefinitionMap 中仅有主配置类这一条记录,项目中所有其他 @Component、@Service、@Bean 等都尚未被发现——这些工作留给 refresh() 中的 invokeBeanFactoryPostProcessors 阶段完成。
4.2 ApplicationContextInitializer:容器的预配置扩展点
applyInitializers() 是 Spring Boot 暴露的另一个扩展点,它在 refresh() 之前执行,允许在容器尚未加载任何用户 Bean 的阶段对其进行配置。ApplicationContextInitializer 的典型用途包括:设置激活的 Profile、注册额外的属性源、预注册基础设施 Bean 定义等。
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {    voidinitialize(C applicationContext);}
Spring Boot 自身也通过 SPI 注册了若干内置 Initializer,例如 SharedMetadataReaderFactoryContextInitializer(共享元数据读取器工厂)和 ConditionEvaluationReportLoggingListener(条件评估报告日志)。
5. 容器的刷新:refresh() 模板方法
prepareContext() 完成后,立即进入 Spring 启动过程中最核心、最复杂的阶段:
// SpringApplication.javaprivate void refreshContext(ConfigurableApplicationContext context) {    if (this.properties.isRegisterShutdownHook()) {        // 注册 JVM 关闭钩子,确保应用正常关闭时容器能够优雅地销毁        shutdownHook.registerApplicationContext(context);    }    refresh(context); // ← 委托给 AbstractApplicationContext.refresh()}
refresh() 是在 AbstractApplicationContext 中以模板方法模式定义的:整个方法体是固定的执行骨架,每一个步骤都是一个方法调用,子类可以通过覆盖其中特定的方法来注入特定场景的逻辑(例如 Web 场景下启动嵌入式服务器)。
5.1 refresh() 的十二步骨架
// AbstractApplicationContext.java@Overridepublic void refresh() throws BeansException, IllegalStateException {    this.startupShutdownLock.lock();    try {        this.startupShutdownThread = Thread.currentThread();        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");        // ① 刷新前的预处理:记录启动时间、设置 active 标志、初始化属性源        prepareRefresh();        // ② 获取 BeanFactory(GenericApplicationContext 直接返回已创建的 DefaultListableBeanFactory)        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();        // ③ 对 BeanFactory 进行标准配置:注册内置 Bean、配置类加载器、添加基础 BeanPostProcessor        prepareBeanFactory(beanFactory);        try {            // ④ 子类扩展点:在 BeanFactory 准备好之后、BeanFactoryPostProcessor 执行前进行定制            //    (ServletWebServerApplicationContext 在此注册 Web 相关的 Scope,如 request/session)            postProcessBeanFactory(beanFactory);            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");            // ⑤ 执行所有 BeanFactoryPostProcessor            //    核心:ConfigurationClassPostProcessor 在此扫描注解,批量注册所有 BeanDefinition            invokeBeanFactoryPostProcessors(beanFactory);            // ⑥ 注册所有 BeanPostProcessor(Bean 创建时的"切面钩子")            registerBeanPostProcessors(beanFactory);            beanPostProcess.end();            // ⑦ 初始化 MessageSource(国际化支持)            initMessageSource();            // ⑧ 初始化 ApplicationEventMulticaster(事件广播器)            initApplicationEventMulticaster();            // ⑨ 子类扩展点:刷新过程中的特殊初始化            //    (ServletWebServerApplicationContext 在此创建并启动嵌入式 Tomcat)            onRefresh();            // ⑩ 注册事件监听器(将 ApplicationListener 的 Bean 注册到广播器)            registerListeners();            // ⑪ 实例化所有非懒加载的单例 Bean ← 最耗时的阶段            finishBeanFactoryInitialization(beanFactory);            // ⑫ 完成刷新:清理资源缓存、发布 ContextRefreshedEvent            finishRefresh();        } catch (RuntimeException | Error ex) {            // 刷新失败:销毁已创建的 Bean,重置 active 标志            destroyBeans();            cancelRefresh(ex);            throw ex;        } finally {            contextRefresh.end();        }    } finally {        this.startupShutdownThread = null;        this.startupShutdownLock.unlock();    }}
十二个步骤构成了容器从"空白"到"就绪"的完整路径。其中有四个步骤是整个 Spring 体系的核心,值得深入展开:步骤③(prepareBeanFactory)、步骤⑤(invokeBeanFactoryPostProcessors)、步骤⑨(onRefresh,Web 场景)和步骤⑪(finishBeanFactoryInitialization)。
5.2 prepareBeanFactory:容器的基础配置
prepareBeanFactory() 为 DefaultListableBeanFactory 注入运行所需的基础设施:
// AbstractApplicationContext.javaprotectedvoidprepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {    // 设置类加载器    beanFactory.setBeanClassLoader(getClassLoader());    // 设置 SpEL 表达式解析器(支持 @Value("#{...}") 语法)    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));    // 设置属性编辑器(String 到各类型的转换)    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));    // 注册核心 BeanPostProcessor:ApplicationContextAwareProcessor    // 负责向实现了 Aware 接口的 Bean 注入框架对象(ApplicationContext、Environment 等)    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));    // 声明若干接口不参与自动装配(这些接口应通过 Aware 回调获取,而非依赖注入)    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);    // ...    // 注册可以被直接注入的特殊依赖(@Autowired BeanFactory / ApplicationContext)    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);    beanFactory.registerResolvableDependency(ApplicationContext.classthis);    // 注册若干内置 Bean(environment、systemProperties、systemEnvironment)    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());    }    // ...}
5.3 invokeBeanFactoryPostProcessors:Bean 定义的全面扫描
这是 refresh() 中最核心的一步,它负责将注解元数据转化为 BeanDefinition,从根本上决定了容器中有哪些 Bean 可以被使用。
BeanFactoryPostProcessor 是一类特殊接口,它在所有 Bean 实例化之前介入,直接对 BeanFactory(即容器本身)进行操作:
public interface BeanFactoryPostProcessor {    // 在容器完成 BeanDefinition 加载后、Bean 实例化前被调用    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)            throws BeansException;}
其子接口 BeanDefinitionRegistryPostProcessor 更进一步,可以在 postProcessBeanFactory 执行之前额外注册新的 BeanDefinition:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {    // 先于 postProcessBeanFactory 执行,可以向 registry 注册新的 BeanDefinition    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)            throws BeansException;}
5.3.1 ConfigurationClassPostProcessor:注解扫描的核心
Spring Boot 中最重要的 BeanDefinitionRegistryPostProcessor 实现是 ConfigurationClassPostProcessor,它是整个注解驱动配置体系的核心引擎:
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()  └── ConfigurationClassParser.parse(candidateComponents)        ├── 解析主配置类(@SpringBootApplication        │     ├── @ComponentScan → 扫描指定包,发现所有 @Component 标注的类        │     │     └── 为每个扫描到的类生成 ScannedGenericBeanDefinition 注册进容器        │     ├── @Import → 导入指定配置类或 ImportSelector/ImportBeanDefinitionRegistrar        │     │     └── AutoConfigurationImportSelector → 加载所有自动配置类(spring.factories        │     └── @Bean → 解析配置类中每个 @Bean 方法        │           └── 生成 ConfigurationClassBeanDefinition 注册进容器        └── 递归处理新发现的配置类(@EnableAutoConfiguration 导入的大量 AutoConfiguration
在 ConfigurationClassPostProcessor 执行完毕后,容器的 beanDefinitionMap 已经包含了应用中所有需要被管理的 Bean 的 BeanDefinition——无论它们是来自 @Component 扫描、@Bean 方法,还是 Spring Boot 的自动配置。
5.3.2 PostProcessor 的执行顺序
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() 对执行顺序有严格管控:
① 执行通过编程方式手动注册的 BeanDefinitionRegistryPostProcessor(优先级最高)② 执行实现了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor(ConfigurationClassPostProcessor 在此处)③ 执行实现了 Ordered 的 BeanDefinitionRegistryPostProcessor④ 执行剩余的 BeanDefinitionRegistryPostProcessor(可能由上一轮新注册进来)⑤ 执行所有 BeanDefinitionRegistryPostProcessor 的 postProcessBeanFactory() 方法⑥ 按相同优先级顺序执行所有 BeanFactoryPostProcessor(如 PropertySourcesPlaceholderConfigurer,解析 @Value("${...}")
5.4 onRefresh:嵌入式 Web 服务器的启动
在 Servlet Web 场景下,onRefresh() 由 ServletWebServerApplicationContext 覆盖实现,负责创建和启动嵌入式 Tomcat:
// ServletWebServerApplicationContext.java@Overrideprotected void onRefresh() {    super.onRefresh();    try {        createWebServer(); // ← 创建并启动嵌入式服务器    } catch (Throwable ex) {        throw new ApplicationContextException("Unable to start web server", ex);    }}private void createWebServer() {    WebServer webServer = this.webServer;    ServletContext servletContext = getServletContext();    if (webServer == null && servletContext == null) {        // 通过 WebServerFactory(TomcatServletWebServerFactory 等)创建服务器        ServletWebServerFactory factory = getWebServerFactory();        this.webServer = factory.getWebServer(getSelfInitializer());        // 注册 Web 服务器的生命周期 Bean        getBeanFactory().registerSingleton("webServerGracefulShutdown", ...);        getBeanFactory().registerSingleton("webServerStartStop", ...);    }    // ...}
值得注意的是,服务器在这里仅完成"创建"(factory.getWebServer()),实际的端口监听(start())发生在更晚的 finishRefresh() → getLifecycleProcessor().onRefresh() 中,届时服务器才真正对外开放连接。
5.5 finishBeanFactoryInitialization:实例化所有单例 Bean
这是 refresh() 中最耗时的步骤,也是 Spring IoC 容器完成"定义"到"实例"跨越的关键时刻:
// AbstractApplicationContext.javaprotected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {    // 初始化 ConversionService(类型转换服务)    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && ...) {        beanFactory.setConversionService(...);    }    // 注册内嵌值解析器(用于解析 @Value 中的 ${} 占位符)    if (!beanFactory.hasEmbeddedValueResolver()) {        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));    }    // 实例化所有 LoadTimeWeaverAware(AspectJ LTW 相关)    // ...    // 冻结 Bean 定义:不再允许注册新的 BeanDefinition    beanFactory.freezeConfiguration();    // 核心:实例化所有非懒加载的单例 Bean    beanFactory.preInstantiateSingletons();}
preInstantiateSingletons() 的实现在 DefaultListableBeanFactory 中,其逻辑本质上是对 beanDefinitionNames 的一次全量遍历:
// DefaultListableBeanFactory.java@Overridepublic void preInstantiateSingletons() throws BeansException {    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);    // 第一阶段:实例化所有非懒加载单例    for (String beanName : beanNames) {        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);        // 跳过:抽象定义、非单例、懒加载        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {            if (isFactoryBean(beanName)) {                // FactoryBean:先实例化 FactoryBean 本身(名称前加 &)                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);                if (bean instanceof SmartFactoryBean<?> smartFactoryBean                        && smartFactoryBean.isEagerInit()) {                    getBean(beanName); // 再实例化 FactoryBean 产生的对象                }            } else {                getBean(beanName); // 普通 Bean:直接实例化            }        }    }    // 第二阶段:触发所有 SmartInitializingSingleton 的回调    // (所有单例已就绪,可以安全地进行跨 Bean 的后初始化操作)    for (String beanName : beanNames) {        Object singletonInstance = getSingleton(beanName);        if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {            smartSingleton.afterSingletonsInstantiated();        }    }}
6. Bean 的加载过程
getBean(beanName) 最终会进入 AbstractBeanFactory.doGetBean(),这是 Bean 加载的核心入口,其逻辑集中体现了缓存策略、作用域处理和依赖解析三个关切的协同:
6.1 doGetBean:获取或创建 Bean
// AbstractBeanFactory.javaprotected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {    String beanName = transformedBeanName(name); // 处理别名和 FactoryBean 的 & 前缀    // ── 第一优先级:从缓存获取 ──    Object sharedInstance = getSingleton(beanName); // 查询三级缓存    if (sharedInstance != null && args == null) {        // 已在缓存中:直接返回(可能经 FactoryBean.getObject() 适配)        return (T) getObjectForBeanInstance(sharedInstance, name, beanName, null);    }    // ── 第二优先级:从父容器获取 ──    BeanFactory parentBeanFactory = getParentBeanFactory();    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {        // 当前容器没有该 Bean 的定义,向父容器委托        return (T) parentBeanFactory.getBean(nameToLookup, args);    }    // ── 创建新实例 ──    // 合并 BeanDefinition(处理 parent 属性继承)    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);    // 处理 depends-on:先创建所有依赖的 Bean    String[] dependsOn = mbd.getDependsOn();    if (dependsOn != null) {        for (String dep : dependsOn) {            registerDependentBean(dep, beanName);            getBean(dep); // 递归        }    }    // 按 scope 创建实例    if (mbd.isSingleton()) {        sharedInstance = getSingleton(beanName,                () -> createBean(beanName, mbd, args)); // ← ObjectFactory,延迟创建        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);    } else if (mbd.isPrototype()) {        // 每次都创建新实例        Object prototypeInstance = createBean(beanName, mbd, args);        beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);    } else {        // 自定义 scope(request/session 等)        String scopeName = mbd.getScope();        Scope scope = this.scopes.get(scopeName);        beanInstance = scope.get(beanName, () -> createBean(beanName, mbd, args));    }    return adaptBeanInstance(name, beanInstance, requiredType);}
6.2 createBean → doCreateBean:Bean 实例的诞生
createBean() 在进入真正的实例化逻辑之前,先给 InstantiationAwareBeanPostProcessor 一次"短路"机会(resolveBeforeInstantiation)——如果某个后置处理器直接返回了对象(如某些 AOP 代理场景),则跳过正常实例化流程。通常情况下,最终进入 doCreateBean():
// AbstractAutowireCapableBeanFactory.javaprotected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {    // ① 实例化:通过构造函数或工厂方法创建 Bean 的原始对象(仅 new,未注入任何属性)    BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);    Object bean = instanceWrapper.getWrappedInstance();    // ② 提前暴露(支持循环依赖)    boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences            && isSingletonCurrentlyInCreation(beanName);    if (earlySingletonExposure) {        // 将 ObjectFactory 放入三级缓存        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));    }    Object exposedObject = bean;    try {        // ③ 属性填充:处理 @Autowired@Value@Resource 注入        populateBean(beanName, mbd, instanceWrapper);        // ④ 初始化:执行 Aware 回调、BeanPostProcessor.postProcessBeforeInitialization、        //           InitializingBean.afterPropertiesSet()、@PostConstruct、init-method        //           BeanPostProcessor.postProcessAfterInitializationAOP 代理在此生成)        exposedObject = initializeBean(beanName, exposedObject, mbd);    } catch (Throwable ex) {        // ...    }    // ⑤ 注册销毁回调(@PreDestroy / DisposableBean / destroy-method    registerDisposableBeanIfNecessary(beanName, bean, mbd);    return exposedObject;}
6.3 initializeBean:Bean 的完整生命周期回调
initializeBean() 集中完成了 Bean 初始化阶段的全部生命周期回调,顺序严格固定:
protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {    // 1. Aware 接口回调:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware    invokeAwareMethods(beanName, bean);    // 2. BeanPostProcessor.postProcessBeforeInitialization()    //    (包括处理 @PostConstruct 的 CommonAnnotationBeanPostProcessor,    //     以及注入 ApplicationContext 的 ApplicationContextAwareProcessor)    Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);    // 3. InitializingBean.afterPropertiesSet() 和 init-method    invokeInitMethods(beanName, wrappedBean, mbd);    // 4. BeanPostProcessor.postProcessAfterInitialization()    //    (Spring AOP 的 AbstractAutoProxyCreator 在此为 Bean 创建代理对象)    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);    return wrappedBean;}
这四个步骤决定了 Bean 对外暴露的最终形态:如果某个 Bean 被 AOP 切面命中,步骤④返回的将是一个代理对象,容器和依赖它的其他 Bean 持有的都是这个代理,而非原始 Bean 实例。
7. 完整流程:从 run() 到 Bean 就绪
SpringApplication.run()  │  ├── createApplicationContext()  │     └── new AnnotationConfigServletWebServerApplicationContext()  │           └── new DefaultListableBeanFactory()   ← 容器在此诞生  │  ├── prepareContext()  │     ├── applyInitializers()                       ← ApplicationContextInitializer 回调  │     └── load(primarySources)  │           └── registry.registerBeanDefinition(主配置类)  ← 仅注册主配置类  │  └── refreshContext()        └── AbstractApplicationContext.refresh()              │              ├── ① prepareRefresh()              ├── ② obtainFreshBeanFactory()          ← 获取 DefaultListableBeanFactory              ├── ③ prepareBeanFactory()              ← 注入基础设施(Aware 处理器、内置 Bean)              ├── ④ postProcessBeanFactory()          ← Web Scope 注册              │              ├── ⑤ invokeBeanFactoryPostProcessors() ← ★ 核心:扫描注解,批量注册 BeanDefinition              │     └── ConfigurationClassPostProcessor              │           ├── @ComponentScan → 扫描包,注册所有 @Component              │           ├── @Import → 加载 AutoConfiguration              │           └── @Bean → 注册工厂方法定义              │              ├── ⑥ registerBeanPostProcessors()     ← 注册 AutowiredAnnotationBeanPostProcessor 等              ├── ⑦ initMessageSource()              ├── ⑧ initApplicationEventMulticaster()              │              ├── ⑨ onRefresh()                      ← ★ Web:创建 Tomcat(尚未 start              │              ├── ⑩ registerListeners()              │              ├── ⑪ finishBeanFactoryInitialization() ← ★ 核心:实例化所有单例 Bean              │     └── preInstantiateSingletons()              │           └── 遍历 beanDefinitionNames → getBean(beanName)              │                 └── doGetBean() → createBean() → doCreateBean()              │                       ├── createBeanInstance()   ← 实例化(new              │                       ├── addSingletonFactory()  ← 三级缓存(循环依赖)              │                       ├── populateBean()         ← 属性注入(@Autowired              │                       └── initializeBean()              │                             ├── Aware 回调              │                             ├── @PostConstruct              │                             ├── afterPropertiesSet() / init-method              │                             └── postProcessAfterInitialization() ← AOP 代理              │              └── ⑫ finishRefresh()                  ← 发布 ContextRefreshedEvent,启动 Tomcat
至此,容器从一张"空白图纸"成长为一个装载着所有就绪 Bean 的"完整运行时环境",SpringApplication.run() 也随即返回,Spring Boot 应用正式进入服务状态。
基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-06-08 17:42:03 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/619286.html
  2. 运行时间 : 0.199687s [ 吞吐率:5.01req/s ] 内存消耗:4,944.92kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=16b0f41fad8b5d5e150b70be92d2e869
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000840s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000894s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000351s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000246s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000470s ]
  6. SELECT * FROM `set` [ RunTime:0.000186s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000581s ]
  8. SELECT * FROM `article` WHERE `id` = 619286 LIMIT 1 [ RunTime:0.001045s ]
  9. UPDATE `article` SET `lasttime` = 1780911723 WHERE `id` = 619286 [ RunTime:0.003533s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000245s ]
  11. SELECT * FROM `article` WHERE `id` < 619286 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000392s ]
  12. SELECT * FROM `article` WHERE `id` > 619286 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000389s ]
  13. SELECT * FROM `article` WHERE `id` < 619286 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.010129s ]
  14. SELECT * FROM `article` WHERE `id` < 619286 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.004145s ]
  15. SELECT * FROM `article` WHERE `id` < 619286 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000888s ]
0.204375s