跳到主要内容

架构文档

本文档详细说明 TabooLib IoC 容器的内部架构、启动流程和核心机制。

版本信息

版本:1.1.0-SNAPSHOT | TabooLib 6.2.x | Kotlin 2.1.0

模块结构与依赖关系

taboolib-ioc-annotation   ← 38 个注解定义(零依赖)
taboolib-ioc-api ← 15 个数据类/接口(依赖 annotation)
taboolib-ioc-core ← 核心实现,26+ 个类(依赖 api)
taboolib-ioc ← 聚合打包模块
taboolib-ioc-example ← 示例插件
test-v1_20 / test-v1_12 ← MC 版本集成测试
点击放大

核心包职责

核心类职责
scanComponentVisitor, ClassScanner, ConfigurationScanner, ComponentScanPackages类扫描、元数据解析、@ComponentScan 包过滤
beanBeanContainer, BeanResolver, BeanRegistry, BeanContainerExtensions容器主入口、Bean 查找与作用域解析
injectInjector, FieldInjector, ConstructorResolver, ObjectInjector, LazyProxyFactory, ValueResolver依赖注入(字段/构造函数/方法/@Value)、@Lazy 代理
lifecycleLifecycleManager, ContainerLifecycle, EventBus生命周期管理、TabooLib 生命周期集成、容器事件
cycleCycleDetector, CycleResolver, CircularDependencyException循环依赖检测、单例早期暴露
aopAopProxyFactory, AdvisorRegistry, AspectScanner, InterceptorChain, JdkDynamicAopProxyAOP 代理(JDK 动态代理)
conditionConditionEvaluator, OnBeanCondition, OnClassCondition, OnMissingBeanCondition, OnMissingClassCondition, OnPropertyCondition条件装配评估
scopeThreadBeanScope, RefreshBeanScope内置自定义作用域
utilKotlinPropertyAnnotationsKotlin 属性注解工具(处理 $annotations 合成方法)

容器启动时序

容器通过 TabooLib 的 @AwakeregisterLifeCycleTask 机制集成到 Bukkit 插件生命周期中。

点击放大

LOAD 阶段 — 组件扫描

入口:ComponentVisitor.scanAll()@Awake(LifeCycle.LOAD)

  1. runningClassMapInJar 加载 Jar 内所有类
  2. 解析 @ComponentScan 注解,确定扫描包范围(ComponentScanPackages.resolve
  3. 按包名过滤候选类(ComponentScanPackages.matches
  4. 阶段一扫描:
    • 对每个候选类调用 ClassScanner.scan() 生成 BeanDefinition
    • 评估类级条件注解(@ConditionalOnClass@ConditionalOnMissingClass@ConditionalOnProperty@Conditional
    • @ConditionalOnBean / @ConditionalOnMissingBean 的延迟到阶段二
    • 通过条件的注册到 BeanRegistry
    • @Configuration 类:ConfigurationScanner.scan() 扫描 @Bean 方法,评估方法级条件注解后注册
    • 加载 @PropertySource 指定的配置文件到 ValueResolver
  5. 阶段二扫描:
    • 评估延迟的 @ConditionalOnBean / @ConditionalOnMissingBean(此时 BeanRegistry 已有阶段一的注册结果)

同时,ObjectInjector.collectObjectClasses() 在 LOAD 阶段收集所有带 @Inject/@Resource 字段的 Kotlin object 类。

ENABLE -100 — 容器初始化

入口:ContainerLifecycleBeanContainer.initialize()

registerBuiltinScopes (thread, refresh)

initializeAspects — 创建切面 Bean 实例 → AspectScanner 解析 Advisor → 注册到 AdvisorRegistry

discoverBeanPostProcessors — 发现并注册 BeanPostProcessor

LifecycleManager.initialize()
├── validateScopes — 验证所有 BeanDefinition 的作用域是否已注册
├── logResolvableDependencyCycles — 对单例 Bean 做循环依赖检测(仅日志警告)
├── topologicalSort — 按 @DependsOn 声明拓扑排序
├── 预初始化 eager singleton(先切面 Bean 后普通 Bean)
│ └── 对每个 Bean 调用 getOrCreateSingleton → createBean
└── 发布 ContainerInitializedEvent

ENABLE -90 — Object 注入

入口:ObjectInjector.injectObjectFields()

  • 遍历 LOAD 阶段收集的 Kotlin object
  • 通过 INSTANCE 静态字段获取 object 单例
  • 对每个 @Inject/@Resource 字段:
    • @Lazy:通过 LazyProxyFactory 创建 JDK 动态代理
    • 不带 @Lazy:直接调用 BeanContainer.getBean() 获取实例并注入

ENABLE -80 — PostEnable 回调

入口:ContainerLifecycleBeanContainer.invokePostEnable()LifecycleManager.invokePostEnable()

  • initializationOrder(Bean 创建顺序)遍历所有已初始化的 singleton
  • 执行每个 Bean 的 @PostEnable 方法
  • @Bean 工厂方法产物,会补充扫描实际类型上的 @PostEnable 方法

DISABLE 100 — 容器关闭

入口:ContainerLifecycleBeanContainer.shutdown()

LifecycleManager.shutdown()
├── 按 initializationOrder 逆序遍历 singleton
├── 执行每个 Bean 的 @PreDestroy 方法
├── 发布 BeanDestroyedEvent
└── 发布 ContainerShutdownEvent

清理 customScopes(调用每个 scope 的 clear())
清理 AdvisorRegistry
清理 CycleResolver
清理 BeanRegistry
清理 manualBeansByName
清理 EventBus
清理 ValueResolver

Bean 创建流程

LifecycleManager.createBean() 是 Bean 实例化的核心方法,处理完整的创建-注入-初始化-代理流程。

点击放大

实例化方式取决于 BeanDefinition 的类型:

类型实例化方式
普通组件(@Component/@Service/@Repository/@ControllerConstructorResolver 选择构造函数 → constructor.newInstance(args)
@Bean 工厂方法产物获取 @Configuration 类实例 → factoryMethod.invoke(configInstance, args)

构造函数/工厂方法参数解析支持 @Lazy 延迟代理(通过 LazyProxyFactory 创建 JDK 动态代理)。

依赖解析流程

依赖解析涉及两个层次:FieldInjector.resolveDependency() 负责入口路由,BeanResolver.resolveBean() 负责实际查找与作用域处理。

点击放大

BeanResolver 还会检查 manualBeansByName(通过 BeanContainer.registerBean() 手动注册的 Bean),作为 BeanRegistry 查找的补充。

条件装配机制

条件装配分两个阶段评估,由 ConditionEvaluator 统一协调:

阶段评估的条件注解时机
阶段一(扫描时)@Conditional@ConditionalOnClass@ConditionalOnMissingClass@ConditionalOnPropertyComponentVisitor.scanAll() 扫描每个类/方法时
阶段二(注册后)@ConditionalOnBean@ConditionalOnMissingBean阶段一全部注册完成后,基于已注册的 BeanDefinition 评估

分两阶段的原因:@ConditionalOnBean 需要知道哪些 Bean 已经注册,因此必须等阶段一完成后才能评估。

条件注解可以标注在:

  • 组件类上(@Component/@Service/@Configuration 等)
  • @Bean 工厂方法上

AOP 代理机制

AOP 基于 JDK 动态代理实现,仅支持实现了接口的 Bean。

初始化流程:

  1. BeanContainer.initializeAspects() — 找到所有 isAspect=true 的 BeanDefinition,创建切面实例
  2. AspectScanner.scan() — 解析切面类中的 @Before/@After/@Around 方法,生成 Advisor 列表
  3. AdvisorRegistry.registerAll() — 注册所有 Advisor

代理包装:

  • createBean 的最后阶段,AopProxyFactory.wrapIfNecessary() 检查 Bean 是否有匹配的 Advisor
  • 切面 Bean 自身不会被代理
  • 匹配时通过 JdkDynamicAopProxy 创建代理,方法调用经过 InterceptorChain 执行通知链

作用域管理

作用域标识实现类行为
singletonsingleton内置(CycleResolver 缓存)容器内唯一实例,预初始化
prototypeprototype内置(每次 createTransient每次请求创建新实例
threadthreadThreadBeanScope线程级缓存,可通过 getThreadScope().clear() 清理
refreshrefreshRefreshBeanScope可刷新缓存,通过 BeanContainer.refreshScope() 触发
自定义任意字符串实现 BeanScope 接口通过 BeanContainer.registerScope() 注册

作用域通过 @Scope("name") 或快捷注解(@ThreadScope@RefreshScope@Prototype)声明。标准作用域(singleton/prototype)不允许被覆盖。

LifecycleManager.validateScopes() 在容器初始化时验证所有 BeanDefinition 引用的作用域是否已注册,未注册则抛出异常。