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. 整体架构与目标
整合后的运行形态可以概括为“三层协作”:
- 进程主入口与 Web 路由:由 tio-boot 负责(
@RequestPath、handler、启动链路) - Spring 生态能力:由 Spring Boot 容器负责(starter、自动配置、Bean 生命周期)
- IOC/AOP 桥接与注入打通:由
jfinal-aop/ tio-boot AOP 管理器负责(Aop.get、字段注入识别、与 Spring 容器协作)
2. Maven 依赖配置
以下依赖组合用于:统一 Spring Boot 依赖版本、引入 Spring Boot 基础能力、引入 tio-boot 与 AOP 能力,并在整合时提供 @Autowired 注入支持。
<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.3.8</jfinal-aop.version>
<main.class>com.litongjava.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>com.litongjava</groupId>
<artifactId>tio-boot</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>com.litongjava</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 启动时间线
- 执行
main TioApplication.run(Applicaton.class, args)启动 tio-boot- tio-boot 扫描
@AComponentScan覆盖范围内组件 - 扫描到
@AConfiguration配置类 - 执行配置类中
@Initialization标注的方法 这一阶段发生在 tio-boot handler 初始化之前 - 在
@Initialization方法中启动 Spring:SpringApplication.run(...) - 开启 AOP 与 Spring 协作:
AopManager.me().setEnableWithSpring(true) - 注册 Spring 上下文:
SpringBeanContextUtils.setContext(context) - 扩展字段注入识别:
Aop.addFetchBeanAnnotation(Autowired.class) - 注册销毁钩子:关闭 Spring
ApplicationContext - 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
package com.litongjava.spring.boot.tio.boot.demo01;
import com.litongjava.annotation.AComponentScan;
import com.litongjava.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
package com.litongjava.spring.boot.tio.boot.demo01.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import com.litongjava.annotation.AConfiguration;
import com.litongjava.annotation.Initialization;
import com.litongjava.hook.HookCan;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.aop.AopManager;
import com.litongjava.jfinal.spring.SpringBeanContextUtils;
import com.litongjava.spring.boot.tio.boot.demo01.Applicaton;
import com.litongjava.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 扫描管理
接口
package com.litongjava.spring.boot.tio.boot.demo01.service;
import java.util.List;
public interface UserService {
List<String> listAll();
}
实现
package com.litongjava.spring.boot.tio.boot.demo01.service;
import java.util.ArrayList;
import java.util.List;
import com.litongjava.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 字段注入
package com.litongjava.spring.boot.tio.boot.demo01.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.litongjava.annotation.RequestPath;
import com.litongjava.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(...) 主动获取
package com.litongjava.spring.boot.tio.boot.demo01.controller;
import java.util.List;
import com.litongjava.annotation.RequestPath;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.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
package com.litongjava.spring.boot.tio.boot.demo01.controller;
import com.litongjava.annotation.RequestPath;
import com.litongjava.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 为例:
tio-boot 启动时扫描
UserController,基于@RequestPath("/user")注册路由请求进入后由 tio-boot 路由匹配到
listAll方法创建/获取 Controller 实例并进行依赖装配
- 字段注入方式:识别到
@Autowired,按扩展规则注入UserService - 主动获取方式:方法内
Aop.get(UserService.class)获取实例
- 字段注入方式:识别到
调用
UserService.listAll()返回数据并序列化响应
示例响应:
[
"user1"
]
6. 常见问题与排查方向
6.1 @Autowired 注入失败
优先检查:
SpringConfig是否被扫描到并执行了@InitializationAop.addFetchBeanAnnotation(Autowired.class)是否执行UserServiceImpl是否在 tio-boot 扫描范围内(@AComponentScan覆盖包路径)- 如果期望从 Spring 注入,则对应实现是否已注册为 Spring Bean(是否具备 Spring 注解与扫描路径)
6.2 Spring Bean 数量异常少
通常由 Spring 扫描路径或缺少 Spring 注解导致。可通过:
GET /spring/beans查看 Spring 实际加载的 Bean 列表进行定位
6.3 进程停止后未退出
通常是 Spring 管理的线程池/连接池未关闭。需确认:
HookCan.me().addDestroyMethod(context::close)是否执行- 是否存在其他非守护线程(例如第三方组件自行创建的线程)
7. 实践建议:职责划分的两种常用策略
tio-boot 管理业务对象,Spring 提供生态组件 业务 Controller/Service 使用
@RequestPath、@AService;数据库、Redis、MQ 等交给 Spring Starter。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(...)主动获取,便于在不同工程风格与排障场景中取舍
