Solon 不是 Spring 的分支或封装它是独立发展的全栈应用开发框架。但在设计哲学上Solon 遵循了 Java 主流的 IoC、AOP、MVC 范式——概念相同注解名不同。Spring Boot 到 Solon 的注解映射、配置迁移、关键差异整理成对照表供迁移参考1、与 Springboot 的常用注解比较Solon 4.0.2Springboot 2.7.16 / 4.1.0说明Inject *Autowired注入Beanby typeInject(name)QualifierAutowired注入Beanby nameInject(${name})Value(${name}) ConfigurationProperties(prefixname)注入配置BindProps(prefixname)ConfigurationProperties(prefixname)绑定属性集SingletonScope(“singleton”)单例Solon 默认是单例Singleton(false)/多例非单例/Scope(“prototype”)原型ImportImport ComponentScan导入组件一般加在启动类上ImportPropertySource导入属性源一般加在启动类上ConfigurationConfiguration配置类BeanBean配置BeanConditionConditionalOnClass ConditionalOnExpression ...配置条件ComponentComponent, Service, Dao, Repository ...托管组件ImportTestPropertySource导入测试属性源RollbackTestRollback执行测试回滚LifecycleBeanInitializingBean DisposableBean组件初始化和销毁AppLoadEndEventApplicationRunner or CommandLineRunner应用加载后运行Solon 4.0.2Java EE / JakartaLifecycleBean::start或 Init 注解PostConstruct组件初始化LifecycleBean::stop或 Destroy 注解PreDestroy组件销毁注1MethodBean只执行一次只在 Configuration 里有效注2Inject 的参数注入只在 MethodBean 和 Constructor 上有效注3Inject 的类注入只在 Configuration类 上有效注4Import 只在 启动类上 或者 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说明SingletonScope(“singleton”)单例每次注入或获取是一个唯一实例Singleton(false)/多例每次注入或获取是一个新实例/Scope(“prototype”)原型每次调用方法是一个新实例/Scope(“request”)每个 web 请求范围是一个新实例类似于 context attr/Scope(“session”)每个 web 会话范围是一个新实例类似于 session state3、与 Spring Mvc 的比较注解方面的区别Solon 4.0.2Springboot 2.7.16 / 4.1.0说明ControllerController,RestController控制器类Remoting远程控制器类即 Rpc 服务端MappingRequestMapping,GetMapping...映射并不完全对等ParamRequestParam请求参数并不完全对等HeaderRequestHeader请求头BodyRequestBody请求体并不完全对等CookieCookieValue请求小饼PathPathVariable请求路径变量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 ListString tags; ... } //别处可以注入复用 Inject UserConfig userConfig;8、与 Springboot 相似的事务支持 Transaction采用 Springboot 相同的事件传播机制及隔离级别。但回滚时不需要指定异常类型Controller public class DemoController{ Db BaseMapperUserModel userService; Transaction Mapping(/user/update) public void udpUser(long user_id, UserModel user){ userService.updateById(user); } }9、与 Springboot 不同的校验方案 ValidSolon 的方案多了“批量参数校验”且强调“可见性”即与处理函数在一起。同时也支持实体的校验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 BaseMapperUserModel 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(typedtrue) 做为某种类型的默认Bean12、不基于 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(SetClass? 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(namelocal, 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.pluginorg.noear.solon.auth.integration.XPluginImp15、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 · 开发者生态社区
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注入Beanby typeInject(name)QualifierAutowired注入Beanby nameInject(${name})Value(${name}) ConfigurationProperties(prefixname)注入配置BindProps(prefixname)ConfigurationProperties(prefixname)绑定属性集SingletonScope(“singleton”)单例Solon 默认是单例Singleton(false)/多例非单例/Scope(“prototype”)原型ImportImport ComponentScan导入组件一般加在启动类上ImportPropertySource导入属性源一般加在启动类上ConfigurationConfiguration配置类BeanBean配置BeanConditionConditionalOnClass ConditionalOnExpression ...配置条件ComponentComponent, Service, Dao, Repository ...托管组件ImportTestPropertySource导入测试属性源RollbackTestRollback执行测试回滚LifecycleBeanInitializingBean DisposableBean组件初始化和销毁AppLoadEndEventApplicationRunner or CommandLineRunner应用加载后运行Solon 4.0.2Java EE / JakartaLifecycleBean::start或 Init 注解PostConstruct组件初始化LifecycleBean::stop或 Destroy 注解PreDestroy组件销毁注1MethodBean只执行一次只在 Configuration 里有效注2Inject 的参数注入只在 MethodBean 和 Constructor 上有效注3Inject 的类注入只在 Configuration类 上有效注4Import 只在 启动类上 或者 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说明SingletonScope(“singleton”)单例每次注入或获取是一个唯一实例Singleton(false)/多例每次注入或获取是一个新实例/Scope(“prototype”)原型每次调用方法是一个新实例/Scope(“request”)每个 web 请求范围是一个新实例类似于 context attr/Scope(“session”)每个 web 会话范围是一个新实例类似于 session state3、与 Spring Mvc 的比较注解方面的区别Solon 4.0.2Springboot 2.7.16 / 4.1.0说明ControllerController,RestController控制器类Remoting远程控制器类即 Rpc 服务端MappingRequestMapping,GetMapping...映射并不完全对等ParamRequestParam请求参数并不完全对等HeaderRequestHeader请求头BodyRequestBody请求体并不完全对等CookieCookieValue请求小饼PathPathVariable请求路径变量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 ListString tags; ... } //别处可以注入复用 Inject UserConfig userConfig;8、与 Springboot 相似的事务支持 Transaction采用 Springboot 相同的事件传播机制及隔离级别。但回滚时不需要指定异常类型Controller public class DemoController{ Db BaseMapperUserModel userService; Transaction Mapping(/user/update) public void udpUser(long user_id, UserModel user){ userService.updateById(user); } }9、与 Springboot 不同的校验方案 ValidSolon 的方案多了“批量参数校验”且强调“可见性”即与处理函数在一起。同时也支持实体的校验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 BaseMapperUserModel 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(typedtrue) 做为某种类型的默认Bean12、不基于 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(SetClass? 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(namelocal, 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.pluginorg.noear.solon.auth.integration.XPluginImp15、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 · 开发者生态社区