Skip to content

tio-boot 整合 spring-boot-starter ​

tio-boot 整合 spring-boot-starter:启动原理与全流程解析

本文给出一套可落地的整合方案:在同一进程中以 tio-boot 作为主启动与路由入口,在 tio-boot 初始化阶段拉起 Spring Boot 容器,并通过 AOP/IOC 桥接实现 @Autowired 注入与 Aop.get(...) 获取 Bean 的互通。文末提供完整代码示例(含 import)与常见问题排查点。

核心结论先说明:

  • TioApplication.run(...) 先启动 tio-boot
  • 标注 @AConfiguration 的配置类会在 tio-boot 的 handler 初始化之前被执行
  • 配置类中通过 @Initialization 方法启动 SpringApplication.run(...)
  • 通过 AopManager、SpringBeanContextUtils、Aop.addFetchBeanAnnotation(Autowired.class) 打通两套容器

1. 整体架构与目标 ​

整合后的运行形态可以概括为“三层协作”:

  1. 进程主入口与 Web 路由:由 tio-boot 负责(@RequestPath、handler、启动链路)
  2. Spring 生态能力:由 Spring Boot 容器负责(starter、自动配置、Bean 生命周期)
  3. IOC/AOP 桥接与注入打通:由 jfinal-aop / tio-boot AOP 管理器负责(Aop.get、字段注入识别、与 Spring 容器协作)

2. Maven 依赖配置 ​

以下依赖组合用于:统一 Spring Boot 依赖版本、引入 Spring Boot 基础能力、引入 tio-boot 与 AOP 能力,并在整合时提供 @Autowired 注入支持。

xml
<properties>
  <java.version>1.8</java.version>
  <maven.compiler.source>${java.version}</maven.compiler.source>
  <maven.compiler.target>${java.version}</maven.compiler.target>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

  <spring-boot.version>2.5.6</spring-boot.version>
  <jfinal-aop.version>1.4.0</jfinal-aop.version>

  <main.class>nexus.io.spring.boot.tio.boot.demo01.Applicaton</main.class>
</properties>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>${spring-boot.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>

  <dependency>
    <groupId>nexus.io</groupId>
    <artifactId>tio-boot</artifactId>
    <version>2.0.6</version>
  </dependency>

  <dependency>
    <groupId>nexus.io</groupId>
    <artifactId>jfinal-aop</artifactId>
    <version>${jfinal-aop.version}</version>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

3. 启动时序与关键点 ​

3.1 启动时间线 ​

  1. 执行 main
  2. TioApplication.run(Applicaton.class, args) 启动 tio-boot
  3. tio-boot 扫描 @AComponentScan 覆盖范围内组件
  4. 扫描到 @AConfiguration 配置类
  5. 执行配置类中 @Initialization 标注的方法 这一阶段发生在 tio-boot handler 初始化之前
  6. 在 @Initialization 方法中启动 Spring:SpringApplication.run(...)
  7. 开启 AOP 与 Spring 协作:AopManager.me().setEnableWithSpring(true)
  8. 注册 Spring 上下文:SpringBeanContextUtils.setContext(context)
  9. 扩展字段注入识别:Aop.addFetchBeanAnnotation(Autowired.class)
  10. 注册销毁钩子:关闭 Spring ApplicationContext
  11. tio-boot handler 初始化完成,对外提供路由服务

3.2 为什么要在 @AConfiguration 阶段启动 Spring ​

因为此时 tio-boot 的核心运行环境尚未进入 handler/路由处理阶段,适合进行:

  • Spring 容器创建与自动配置
  • AOP/IOC 桥接开关与全局上下文注入
  • 注入规则扩展(让 tio-boot 认识 @Autowired)
  • 生命周期闭环(tio-boot 停止时关闭 Spring)

4. 完整代码示例(含 import) ​

4.1 应用入口:先启动 tio-boot ​

java
package nexus.io.spring.boot.tio.boot.demo01;

import nexus.io.annotation.AComponentScan;
import nexus.io.tio.boot.TioApplication;

@AComponentScan
public class Applicaton {
  public static void main(String[] args) {
    long start = System.currentTimeMillis();
    TioApplication.run(Applicaton.class, args);
    long end = System.currentTimeMillis();
    System.out.println(end - start + "(ms)");
  }
}

4.2 Spring 整合配置:在 tio-boot 初始化阶段启动 Spring ​

java
package nexus.io.spring.boot.tio.boot.demo01.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;

import nexus.io.annotation.AConfiguration;
import nexus.io.annotation.Initialization;
import nexus.io.hook.HookCan;
import nexus.io.jfinal.aop.Aop;
import nexus.io.jfinal.aop.AopManager;
import nexus.io.jfinal.spring.SpringBeanContextUtils;
import nexus.io.spring.boot.tio.boot.demo01.Applicaton;
import nexus.io.tio.utils.environment.EnvUtils;

@AConfiguration
public class SpringConfig {

  @Initialization
  public void config() {
    // 1) 启动 Spring Boot 容器
    ConfigurableApplicationContext context =
        SpringApplication.run(Applicaton.class, EnvUtils.getArgs());

    // 2) 开启 tio-boot AOP 与 Spring 的协作模式
    AopManager.me().setEnableWithSpring(true);

    // 3) 挂载 Spring 上下文,便于在 tio-boot 体系内访问
    SpringBeanContextUtils.setContext(context);

    // 4) 让 tio-boot Bean 支持 Spring 的 @Autowired 注解注入
    Aop.addFetchBeanAnnotation(Autowired.class);

    // 5) 统一销毁:tio-boot 停止时关闭 Spring 容器
    HookCan.me().addDestroyMethod(context::close);
  }
}

要点说明:

  • @AConfiguration 使该类在 tio-boot 启动扫描阶段被发现
  • @Initialization 方法会在 handler 初始化之前执行
  • Aop.addFetchBeanAnnotation(Autowired.class) 是字段注入打通的关键

4.3 Service 定义与实现:由 tio-boot 扫描管理 ​

接口 ​

java
package nexus.io.spring.boot.tio.boot.demo01.service;

import java.util.List;

public interface UserService {
  List<String> listAll();
}

实现 ​

java
package nexus.io.spring.boot.tio.boot.demo01.service;

import java.util.ArrayList;
import java.util.List;

import nexus.io.annotation.AService;

@AService
public class UserServiceImpl implements UserService {

  @Override
  public List<String> listAll() {
    String user1 = "user1";
    List<String> users = new ArrayList<>();
    users.add(user1);
    return users;
  }
}

说明:

  • @AService 使实现类进入 tio-boot 的 IOC/AOP 管理体系
  • 是否同时交由 Spring 管理取决于是否添加 Spring 注解(如 @Service)以及 Spring 扫描范围;本文示例以 tio-boot 管理业务 Bean 为主

4.4 Controller:tio-boot 路由入口与两种 Bean 获取方式 ​

方式一:@Autowired 字段注入 ​

java
package nexus.io.spring.boot.tio.boot.demo01.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import nexus.io.annotation.RequestPath;
import nexus.io.spring.boot.tio.boot.demo01.service.UserService;

@RequestPath("/user")
public class UserController {

  @Autowired
  private UserService userService;

  public List<String> listAll() {
    return userService.listAll();
  }
}

成立的前提是:在 SpringConfig 中执行了

  • AopManager.me().setEnableWithSpring(true)
  • Aop.addFetchBeanAnnotation(Autowired.class)

方式二:Aop.get(...) 主动获取 ​

java
package nexus.io.spring.boot.tio.boot.demo01.controller;

import java.util.List;

import nexus.io.annotation.RequestPath;
import nexus.io.jfinal.aop.Aop;
import nexus.io.spring.boot.tio.boot.demo01.service.UserService;

@RequestPath("/user")
public class UserController {

  public List<String> listAll() {
    return Aop.get(UserService.class).listAll();
  }
}

说明:

  • Aop.get(Class) 会向 tio-boot AOP/IOC 管理器请求实例
  • 开启与 Spring 协作后,获取策略可具备“跨容器兜底/协作”的可能(具体优先级与实现有关)

4.5 Spring 容器自检接口:列出 Spring Bean ​

java
package nexus.io.spring.boot.tio.boot.demo01.controller;

import nexus.io.annotation.RequestPath;
import nexus.io.jfinal.spring.SpringBeanContextUtils;

@RequestPath("/spring")
public class SpringController {

  public String[] beans() {
    return SpringBeanContextUtils.getContext().getBeanDefinitionNames();
  }
}

用途:

  • 快速验证 Spring 容器已成功启动
  • 验证 SpringBeanContextUtils.setContext(context) 桥接生效

5. 请求链路说明:访问 /user/listAll 会发生什么 ​

以 http://localhost/user/listAll 为例:

  1. tio-boot 启动时扫描 UserController,基于 @RequestPath("/user") 注册路由

  2. 请求进入后由 tio-boot 路由匹配到 listAll 方法

  3. 创建/获取 Controller 实例并进行依赖装配

    • 字段注入方式:识别到 @Autowired,按扩展规则注入 UserService
    • 主动获取方式:方法内 Aop.get(UserService.class) 获取实例
  4. 调用 UserService.listAll() 返回数据并序列化响应

示例响应:

json
[
  "user1"
]

6. 常见问题与排查方向 ​

6.1 @Autowired 注入失败 ​

优先检查:

  1. SpringConfig 是否被扫描到并执行了 @Initialization
  2. Aop.addFetchBeanAnnotation(Autowired.class) 是否执行
  3. UserServiceImpl 是否在 tio-boot 扫描范围内(@AComponentScan 覆盖包路径)
  4. 如果期望从 Spring 注入,则对应实现是否已注册为 Spring Bean(是否具备 Spring 注解与扫描路径)

6.2 Spring Bean 数量异常少 ​

通常由 Spring 扫描路径或缺少 Spring 注解导致。可通过:

  • GET /spring/beans 查看 Spring 实际加载的 Bean 列表进行定位

6.3 进程停止后未退出 ​

通常是 Spring 管理的线程池/连接池未关闭。需确认:

  • HookCan.me().addDestroyMethod(context::close) 是否执行
  • 是否存在其他非守护线程(例如第三方组件自行创建的线程)

7. 实践建议:职责划分的两种常用策略 ​

  1. tio-boot 管理业务对象,Spring 提供生态组件 业务 Controller/Service 使用 @RequestPath、@AService;数据库、Redis、MQ 等交给 Spring Starter。

  2. Spring 管理业务对象,tio-boot 作为高性能网络宿主或补充模块 业务主要使用 Spring 注解体系;tio-boot 提供特定网络能力或轻量化模块。

示例工程更贴近策略 1。


8. 小结 ​

  • @AConfiguration 配置类会在 tio-boot handler 初始化之前执行,适合作为 Spring Boot 启动与桥接的切入点
  • 通过 SpringApplication.run 启动 Spring 容器后,使用 AopManager 打开协作模式、使用 SpringBeanContextUtils 暴露上下文、使用 Aop.addFetchBeanAnnotation(Autowired.class) 扩展注入规则,即可完成两套体系的互通
  • Controller 既可采用 @Autowired 注入,也可采用 Aop.get(...) 主动获取,便于在不同工程风格与排障场景中取舍

示例代码地址

MIT Licensed