当前位置: 首页 > news >正文

Spring Boot 与 Solon 比较,相互迁移实战指南

Solon 不是 Spring 的分支或封装,它是独立发展的全栈应用开发框架。但在设计哲学上,Solon 遵循了 Java 主流的 IoC、AOP、MVC 范式——概念相同,注解名不同

Spring Boot 到 Solon 的注解映射、配置迁移、关键差异整理成对照表,供迁移参考

1、与 Springboot 的常用注解比较

Solon 4.0.2Springboot 2.7.16 / 4.1.0说明
@Inject *@Autowired注入Bean(by type)
@Inject("name")@Qualifier+@Autowired注入Bean(by name)
@Inject("${name}")@Value("${name}") + @ConfigurationProperties(prefix="name")注入配置
@BindProps(prefix="name")@ConfigurationProperties(prefix="name")绑定属性集
@Singleton@Scope(“singleton”)单例(Solon 默认是单例)
@Singleton(false)/多例(非单例)
/@Scope(“prototype”)原型
@Import@Import + @ComponentScan导入组件(一般加在启动类上)
@Import@PropertySource导入属性源(一般加在启动类上)
@Configuration@Configuration配置类
@Bean@Bean配置Bean
@Condition@ConditionalOnClass + @ConditionalOnExpression ...配置条件
@Component@Component, @Service, @Dao, @Repository ...托管组件
@Import@TestPropertySource导入测试属性源
@Rollback@TestRollback执行测试回滚
LifecycleBeanInitializingBean + DisposableBean组件初始化和销毁
AppLoadEndEventApplicationRunner or CommandLineRunner应用加载后运行
Solon 4.0.2Java EE / Jakarta
LifecycleBean::start
或 @Init 注解
@PostConstruct组件初始化
LifecycleBean::stop
或 @Destroy 注解
@PreDestroy组件销毁
  • 注1:Method@Bean,只执行一次(只在 @Configuration 里有效)
  • 注2:@Inject 的参数注入,只在 Method@Bean 和 Constructor 上有效
  • 注3:@Inject 的类注入,只在 @Configuration类 上有效
  • 注4:@Import 只在 启动类上 或者 @Configuration类 上有效

2、与 Springboot 组件的差别

  • 动态代理
Solon 4.0.2Springboot 2.7.16 / 4.1.0
只对组件的 public 函数“按需”代理(即有拦截注册时)对组件的 public、protected 函数进行代理
  • 器注册
Solon 4.0.2Springboot 2.7.16 / 4.1.0
需要配置 name 才会按名字注册(才能按名字获取)会自动按“类名”作为 name 进行注册
  • 作用域
Solon 4.0.2Springboot 2.7.16 / 4.1.0说明
@Singleton@Scope(“singleton”)单例(每次注入或获取,是一个唯一实例)
@Singleton(false)/多例(每次注入或获取,是一个新实例)
/@Scope(“prototype”)原型(每次调用方法,是一个新实例)
/@Scope(“request”)每个 web 请求范围,是一个新实例(类似于 context attr)
/@Scope(“session”)每个 web 会话范围,是一个新实例(类似于 session state)

3、与 Spring Mvc 的比较

  • 注解方面的区别
Solon 4.0.2Springboot 2.7.16 / 4.1.0说明
@Controller@Controller,@RestController控制器类
@Remoting远程控制器类(即 Rpc 服务端)
@Mapping@RequestMapping,@GetMapping...映射(并不完全对等)
@Param@RequestParam请求参数(并不完全对等)
@Header@RequestHeader请求头
@Body@RequestBody请求体(并不完全对等)
@Cookie@CookieValue请求小饼
@Path@PathVariable请求路径变量
@Produces/声明输出内容类型
@Consumes/声明输入内容类型
  • 映射的区别

Solon 的@Mapping函数不支持多路径的映射,且只限 public 函数。但是可以通过“本地网关”,为一批 action 添加不同的地址前缀。

  • 控制器继承的区别

Solon 控制器继承时,支持基类的@Mappingpublic 函数

4、重要的区别,Solon 不是基于 Servlet 的开发框架

  • 与 Springboot 相似的体验,但使用 Context 包装请求上下文(底层为:Context + Handler 架构)。Helloworld 效果:
@SolonMain public class App{ public static void main(String[] args){ Solon.start(App.class, args); } } @Controller public class Demo{ @Inject("${app.name}") String appName; @Mapping("/") public Object home(String name){ return appName + ": Hello " + name; } }
  • 与 Servlet 常见类比较
Solon 4.0.2Springboot 2.7.16 / 4.1.0说明
ContextHttpServletRequest + HttpServletResponse请求上下文
SessionStateHttpSession请求会话状态类
UploadedFileMultipartFile文件上传接收类
DownloadedFile文件下载输出类
ModelAndViewModelAndView模型视图输出类
  • Solon 适配有:jdkhttp、smarthttp、jetty、undertow、vert.x、netty、websocket 等各种通讯容器。

5、Solon 不支持属性设置注入

  • 不支持的:
@Component public class DemoCom { private B b; public void setB(@Inject B b){ this.b = b; } }
  • 支持的(字段,或构造器参数,或小豆方法参数):
@Component public class DemoCom { private final A a; @Inject private B b; public Demo(A a){ this.a = a; } } @Configuration public class DemoConfig{ @Bean public void a(A a) { //... } }

6、Solon 可以更自由获取配置

@Component public class Demo{ //注入配置 @Inject("${user.name}") private String userName; //手动获取配置 private String userName = Solon.cfg().get("user.name"); }

7、Solon 配置注解结构体

@Inject("${user.config}") @Configuration public class UserConfig{ public String name; public List<String> tags; ... } //别处可以注入复用 @Inject UserConfig userConfig;

8、与 Springboot 相似的事务支持 @Transaction

  • 采用 Springboot 相同的事件传播机制及隔离级别。但回滚时,不需要指定异常类型
@Controller public class DemoController{ @Db BaseMapper<UserModel> userService; @Transaction @Mapping("/user/update") public void udpUser(long user_id, UserModel user){ userService.updateById(user); } }

9、与 Springboot 不同的校验方案 @Valid

  • Solon 的方案多了“批量参数校验”,且强调“可见性”(即与处理函数在一起)。同时也支持实体的校验
@Valid @Controller public class DemoController { @NoRepeatSubmit @NotNull({"name", "icon", "mobile"}) //在函数这边,可见性更好 //不过显得乱 @Mapping("/valid") public String test(String name, String icon, @Pattern("13\\d{9}") String mobile) { return "OK"; } @Whitelist @Mapping("/valid/test2") public String test2() { return "OK"; } @Mapping("/valid/test3") public String test3(@Validated UserModel user) { return "OK"; } }

10、基于标签管理的缓存支持 @Cache,与 Springboot 略有不同

  • 支持Key的缓存管理。同时增加了基于“标签”的缓存管理,避免不必要的Key冲突
@Controller public class DemoController{ @Db BaseMapper<UserModel> userService; @CacheRemove(tags = "user_${user_id}") @Mapping("/user/update") public void udpUser(int user_id, UserModel user){ userService.updateById(user); } @Cache(tags = "user_${user_id}") public UserModel getUser(int user_id){ return userService.selectById(user_id); } }

11、相似的 @Bean 设计

  • 相似的特性,但可以返回 void。且,需与 @Configuration 协同使用
// // 一个数据主从库的示例 // @Configuration public class Config { @Bean(name = "db1", typed = true) public DataSource db1(@Inject("${test.db1}") HikariDataSource dataSource) { return dataSource; } @Bean("db2") public DataSource db2(@Inject("${test.db2}") HikariDataSource dataSource) { return dataSource; } }
  • 使用 @Bean(typed=true) 做为某种类型的默认Bean

12、不基于 Servlet,却很有 Servlet 亲和度。当使用 servlet 相关的组件时(也支持jsp + tld)

  • 支持 Servlet 请求与响应对象注入
@Mapping("/demo/") @Controller public class DemoController { @Mapping("hello") public void hello(HttpServletRequest req, HttpServletResponse res){ //... } }
  • 支持 ServletContainerInitializer 配置
@Configuration public class DemoConfiguration implements ServletContainerInitializer{ @Override public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException { //... } }
  • 支持 Servlet api 注解
@WebFilter("/demo/*") public class DemoFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException { res.getWriter().write("Hello,我把你过滤了"); } }

13、专属 Rpc 客户端组件:Nami

  • 类似于 Springboot + Feign 的关系,但 Nami 更简洁且支持 socket 通道( Solon 也可以用 Feign )
//[定义接口],一般情况下不需要加任何注解 // public interface UserService { UserModel getUser(Integer userId); } //[服务端] @Remoting,即为远程组件 // @Mappin("user") @Remoting public class UserServiceImpl implements UserService{ public UserModel getUser(Integer userId){ return ...; } } //[消费端] // @Mapping("demo") @Controller public class DemoController { //直接指定服务端地址 @NamiClient("http://localhost:8080/user/") UserService userService; //使用负载均衡 @NamiClient(name="local", path="/user/") UserService userService2; @Mapping("test") public void test() { UserModel user = userService.getUser(12); System.out.println(user); user = userService2.getUser(23); System.out.println(user); } } /** * 定义一个负载器(可以对接发现服务) * */ @Component("local") public class RpcUpstream implements LoadBalance { @Override public String getServer() { return "http://localhost:8080"; } }

14、Solon 的加强版 Spi 扩展机制 - 具备可编程性

  • 新建模块,并实现Plugin接口(以增加 @AuthLogined 注解支持为例)
public class XPluginImpl implements Plugin { @Override public void start(AppContext context) { context.beanInterceptorAdd(AuthLogined.class, new LoginedInterceptor()); } }
  • 增加配置文件
src/main/resources/META-INF/solon/solon.auth.properties
  • 增加配置内容,打包发布即可
solon.plugin=org.noear.solon.auth.integration.XPluginImp

15、Ioc/Aop 扩展, 提前注册 + 扫描一次(也是启动快的原因之一)

  • 注册‘构建器’处理。以注册 @Controller 构建器为例:
Solon.context().beanBuilderAdd(Controller.class, (clz, bw, anno) -> { //内部实现,可参考项目源码 //构建器,可以获取类型并进行加工 new HandlerLoader(bw).load(Solon.global()); }); //效果 @Controller public class DemoController{ }
  • 注册'注入器'处理。以注册 @Inject 注入器为例:
Solon.context().beanInjectorAdd(Inject.class, ((fwT, anno) -> { //内部实现,可参考项目源码 //注入器,可以根据目标生成需要的数据并赋值 beanInject(fwT, anno.value(), anno.autoRefreshed()); })); //效果 @Controller public class DemoController{ @Inject UserService userService; }
  • 注册'拦截器'处理。以注册 @Transaction 拦截器为例:
//拦截器,可以获取执行动作链 Solon.context().beanInterceptorAdd(Tran.class, new TranInterceptor(), 120); //效果 @Component public class UserService{ @Transaction public void addUser(User user){ } }
  • 注册'提取器'处理。以注册 @CloudJob 提取器为例:
//内部实现,可参考项目源码 //提取器,可以提取被注解的函数 Solon.context().beanExtractorAdd(CloudJob.class, CloudJobExtractor.instance); //效果 //提取器只对组件有效 @Component public class Job{ @CloudJob public void statUserJob(){ } }
Spring Boot的发展方向
  • 继续完善云原生支持
  • 优化启动性能
  • 增强对GraalVM原生镜像的支持
  • 简化配置和部署流程
Solon的发展方向
  • 进一步优化性能和资源使用
  • 扩展AI和机器学习支持
  • 增强对边缘计算的支持
  • 完善国际化社区建设

参考:

无耳 Solon (OpenSolon) | 与 Spring Boot 的区别(或迁移参考)

OSCHINA - 开源 × AI · 开发者生态社区

http://www.jsqmd.com/news/1096948/

相关文章:

  • Cadence Allegro PCB Designer实战:从零到一绘制标准PCB封装
  • qrcode.vue:Vue生态中的专业二维码生成解决方案
  • Parsedown终极指南:3步打造高效Markdown解析工作流
  • 杨洋亮相青岛啤酒“白啤更懂夏的嗨”派对 共赴夏日之约
  • Kazumi番剧播放器:如何通过插件扩展实现全网动漫自由观看
  • 【全网最详细】Sucrose Wallpaper Engine下载免费版 动态桌面壁纸软件安装图解(2026最新)
  • 从Wireshark到NpCap:动手构建网络协议解析与流量监控工具
  • ArkTS常用组件知识点整理
  • AGGrid自定义cellRenderer下tooltipShowMode不生效如何处理?
  • 3步搞定艾尔登法环存档管理:终极角色迁移方案
  • Multisim14丨界面布局异常恢复丨实战排查指南
  • 从零到一:基于STM8的125KHz RFID读卡器实现与曼彻斯特码解析实战
  • ORBSLAM3实战:手把手教你将KITTI数据集适配VIO/IMU模式,并完成精度评估
  • OpenAI API 0613更新深度解析:从GPT-3.5-turbo-16k到函数调用的实战指南
  • 红帽 Linux 零基础完整学习笔记 5
  • 从跑分到洞察:CPU性能评估工具全解析与实战指南
  • Yahoo Finance API:.NET开发者的金融数据革命性解决方案
  • 从编译产物到智能索引:详解gen_compile_commands.py生成compile_commands.json的实战路径
  • 从理论到实践:积极心理学与情绪智慧如何赋能研究生科研与生活
  • 深度解析Untrunc:开源视频修复工具的技术实现与实战应用
  • Python量化交易数据获取的终极解决方案:efinance免费金融数据库完全指南
  • AI智能审核技术架构解析:规则引擎与大模型协同的双重拦截
  • MCP 会取代 API 吗?普通开发者应该怎么理解它?
  • 20美元革命性突破:打造你的专属超声波定向音响系统
  • 深圳亚马逊卖家做GEO,哪家能提升站外AI流量?
  • STM32F407硬件SPI驱动GD25Q32闪存,从接线到读写数据的保姆级教程
  • 通用大模型 vs 行业垂类 vs 自建小模型:差 3 个点,和差23 个点
  • 深度学习图模型的优势、学习与深度学习方法(九十二)
  • 从Latte到StreamingT2V:一文看懂开源视频生成模型的“时空注意力”到底怎么玩的
  • 前端实现打包后自动上传代码到服务器