Code Monkey home page Code Monkey logo

go-spring's Introduction

logo
license go-version release

如果你想参与 Go-Spring 项目的研发和管理,欢迎加入项目团队,你可以是擅长编码的技术极客,可以是擅长项目管理的沟通达人, 可以是擅长撰写文档的文字高手,Go-Spring 项目团队都热切欢迎你的加入!

如果你觉得 Go-Spring 项目很棒,但是没有时间亲身加入,你也可以通过捐赠的方式助力和守护 Go-Spring 项目的成长,所有 捐赠的资金都将透明地用于 Go-Spring 项目团队的人员激励和项目推广。

最后,欢迎 🌟 本项目,你的关注是我和团队继续前进的动力!破釜沉舟,百二秦关终属楚;卧薪尝胆,三千越甲可吞吴!

Go-Spring 的愿景是让 Go 程序员也能用上如 Java Spring 那般威力强大的编程框架,立志为用户提供简单、安全、可信赖的编程体验。

其特性如下:

  1. 提供了完善的 IoC 容器,支持依赖注入、属性绑定;
  2. 提供了强大的启动器框架,支持自动装配、开箱即用;
  3. 提供了常见组件的抽象层,支持灵活地替换底层实现;
    3.1 抽象 web 框架,echo 和 gin 可以灵活替换。
    3.2 抽象 redis 框架,redigo 和 go-redis 可以灵活替换。
  4. 遵循最小依赖原则,部分组件零依赖,避免依赖地狱;
    4.1 提供 assert 包,满足日常测试断言的需求。
    4.2 提供 cast 包,满足日常数据转换的需求。
    4.3 提供 atomic 包,方便并发安全的存取数据。
  5. 首创基于框架的流量录制和回放技术,让测试更简单;
  6. 实现 Log4J 的日志架构,让日志管理更简单、更强大;

Go-Spring 当前使用 Go1.14 进行开发,使用 Go Modules 进行依赖管理。

项目列表

路线图

  • 完善 Base 基础库的能力。
    • 实现 assert 包常用的断言能力。
    • 实现 atomic 包常用原子操作的封装。
    • 实现 cast 包常用的类型转换。
    • 实现上下文缓存组件包 knife。
    • 实现进程内缓存组件包 cache。
    • 实现 jsonpath 操作 json 数据的能力。
  • 实现基本完善的 IoC 和 Boot 框架。
    • 实现读取应用程序配置的组件。
    • 实现 IoC 依赖注入框架。
    • 实现 Boot 自动装配框架。
  • 实现 Log4J 风格的日志框架。
  • 实现 Web 框架以及对 Echo 和 Gin 的适配。
    • 实现 Web 服务器以及中间件能力。
    • 实现 Echo 适配以及开箱即用的能力。
    • 实现 Gin 适配以及开箱即用的能力。
  • 实现 Redis 框架以及对 Redigo 和 Go-Redis 的适配。
    • 实现 Redis 客户端以及中间件能力。
    • 实现 Redigo 适配以及开箱即用的能力。
    • 实现 Go-Redis 适配以及开箱即用的能力。
  • 实现 MyBatis 风格的 SQL 框架。
  • 实现 MQ 框架以及对 RabbitMQ 和 RocketMQ 的适配。
    • 实现 MQ 服务器和客户端能力。
    • 实现 RabbitMQ 适配以及开箱即用的能力。
    • 实现 RocketMQ 适配以及开箱即用的能力。
  • 实现 go-mongo 开箱即用的能力。
  • 实现 gorm 开箱即用的能力。
  • 实现基本完善的流量录制和回放框架。
  • 实现 Web 组件的流量录制和回放。
  • 实现 Redis 组件的流量录制和回放。
  • 实现 Gorm 组件的流量录制和回放。
  • 实现 MQ 组件的流量录制和回放。
  • 实现前后端分离的应用程序组织标准。

优秀教程

《Go-Spring 学习笔记》

《Go-Spring 入门篇》

《从零构建 Go-Spring 项目》

IoC 容器

Go-Spring 不仅实现了如 Java Spring 那般功能强大的 IoC 容器,还扩充了 Bean 的概念。在 Go 中,对象(即指针)、数组、Map、函数指针,这些都是 Bean,都可以放到 IoC 容器里。

常用的 Java Spring 注解 对应的 Go-Spring 实现
@Value value:"${}"
@Autowired @Qualifier @Required autowire:"?"
@Configurable WireBean()
@Profile ConditionOnProfile()
@Primary Primary()
@DependsOn DependsOn()
@ConstructorBinding RegisterBeanFn()
@ComponentScan @Indexed Package Import
@Conditional NewConditional()
@ConditionalOnExpression NewExpressionCondition()
@ConditionalOnProperty NewPropertyValueCondition()
@ConditionalOnBean NewBeanCondition()
@ConditionalOnMissingBean NewMissingBeanCondition()
@ConditionalOnClass Don't Need
@ConditionalOnMissingClass Don't Need
@Lookup ——

属性绑定

Go-Spring 不仅支持对普通数据类型进行属性绑定,也支持对自定义值类型进行属性绑定,而且还支持对结构体属性的嵌套绑定。

type DB struct {
	UserName string `value:"${username}"`
	Password string `value:"${password}"`
	Url      string `value:"${url}"`
	Port     string `value:"${port}"`
	DB       string `value:"${db}"`
}

type DbConfig struct {
	DB []DB `value:"${db}"`
}

上面这段代码可以通过下面的配置进行绑定:

db:
  -
    username: root
    password: 123456
    url: 1.1.1.1
    port: 3306
    db: db1
  -
    username: root
    password: 123456
    url: 1.1.1.1
    port: 3306
    db: db2

Boot 框架

Go-Spring 提供了一个功能强大的启动器框架,不仅实现了自动加载、开箱即用,而且可以非常容易的开发自己的启动器模块,使得代码不仅仅是库层面的复用。

快速示例

下面的示例使用 v1.1.0-rc2 版本测试通过。

import (
	"fmt"

	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	_ "github.com/go-spring/starter-echo"
)

func init() {
	gs.Object(new(Controller)).Init(func(c *Controller) {
		gs.GetMapping("/", c.Hello)
	})
}

type Controller struct {
	GOPATH string `value:"${GOPATH}"`
}

func (c *Controller) Hello(ctx web.Context) {
	ctx.String("%s - hello world!", c.GOPATH)
}

func main() {
	fmt.Println(gs.Run())
}

启动上面的程序,控制台输入 curl http://localhost:8080/, 可得到如下结果:

/Users/didi/go - hello world!

更多示例: https://github.com/go-spring/go-spring/tree/master/examples

普通路由

package main

import (
	"fmt"

	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	_ "github.com/go-spring/starter-echo"
)

func main() {
	gs.GetMapping("/a/b/c", func(ctx web.Context) {
		ctx.String("OK")
	})
	fmt.Println(gs.Run())
}
➜ curl http://127.0.0.1:8080/a/b/c
OK

java 风格路由

package main

import (
	"fmt"

	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	_ "github.com/go-spring/starter-echo"
)

func main() {
	gs.GetMapping("/:a/b/:c/{*:d}", func(ctx web.Context) {
		ctx.String("a=%s b=%s *=%s\n", ctx.PathParam("a"), ctx.PathParam("c"), ctx.PathParam("*"))
		ctx.String("a=%s b=%s *=%s\n", ctx.PathParam("a"), ctx.PathParam("c"), ctx.PathParam("d"))
	})
	fmt.Println(gs.Run())
}
➜ curl http://127.0.0.1:8080/a/b/c/d
a=a b=c *=d
a=a b=c *=d

echo 风格路由

package main

import (
	"fmt"

	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	_ "github.com/go-spring/starter-echo"
)

func main() {
	gs.GetMapping("/:a/b/:c/*", func(ctx web.Context) {
		ctx.String("a=%s c=%s *=%s", ctx.PathParam("a"), ctx.PathParam("c"), ctx.PathParam("*"))
	})
	fmt.Println(gs.Run())
}
➜ curl http://127.0.0.1:8080/a/b/c/d
a=a c=c *=d

gin 风格路由

package main

import (
	"fmt"

	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	_ "github.com/go-spring/starter-echo"
)

func main() {
	gs.GetMapping("/:a/b/:c/*d", func(ctx web.Context) {
		ctx.String("a=%s b=%s *=%s\n", ctx.PathParam("a"), ctx.PathParam("c"), ctx.PathParam("*"))
		ctx.String("a=%s b=%s *=%s\n", ctx.PathParam("a"), ctx.PathParam("c"), ctx.PathParam("d"))
	})
	fmt.Println(gs.Run())
}
➜ curl http://127.0.0.1:8080/a/b/c/d
a=a b=c *=d
a=a b=c *=d

文件服务器

package main

import (
	"fmt"
	"net/http"

	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	_ "github.com/go-spring/starter-echo"
)

func main() {
	gs.HandleGet("/public/*", web.WrapH(http.StripPrefix("/public/", http.FileServer(http.Dir("public")))))
	fmt.Println(gs.Run())
}

然后在项目下创建一个 public 目录,里面创建一个内容为 hello world! 的 a.txt 文件。

➜ curl http://127.0.0.1:8080/public/a.txt
hello world!

BIND 模式

package main

import (
	"context"
	"fmt"

	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	_ "github.com/go-spring/starter-echo"
)

type HelloReq struct {
	Name string `form:"name"`
}

type HelloResp struct {
	Body string `json:"body"`
}

func main() {
	gs.GetBinding("/hello", func(ctx context.Context, req *HelloReq) *web.RpcResult {
		return web.SUCCESS.Data(&HelloResp{Body: "hello " + req.Name + "!"})
	})
	fmt.Println(gs.Run())
}
➜ curl 'http://127.0.0.1:8080/hello?name=lvan100' 
{"code":200,"msg":"SUCCESS","data":{"body":"hello lvan100!"}}

中间件

Basic Auth

package main

import (
	"fmt"

	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	"github.com/go-spring/spring-echo"
	_ "github.com/go-spring/starter-echo"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
)

func main() {

	gs.Provide(func( /* 可以通过配置将用户名密码传进来 */ ) web.Filter {
		m := middleware.BasicAuth(func(u string, p string, e echo.Context) (bool, error) {
			if u == "lvan100" && p == "123456" {
				return true, nil
			}
			return false, nil
		})
		return SpringEcho.Filter(m)
	})

	gs.GetMapping("/hello", func(ctx web.Context) {
		ctx.String("hello %s!", ctx.QueryParam("name"))
	})

	fmt.Println(gs.Run())
}
➜ curl 'http://127.0.0.1:8080/hello?name=lvan100'
Unauthorized
➜ curl 'http://127.0.0.1:8080/hello?name=lvan100' -H'Authorization: Basic bHZhbjEwMDoxMjM0NTY='
{"code":200,"msg":"SUCCESS","data":{"body":"hello lvan100!"}}

详细文档

https://docs.lavend.net/

项目成员

发起者

@lvan100 (LiangHuan)

贡献者

特别鸣谢

@shenqidebaozi

如何成为贡献者?提交有意义的 PR 或者需求,并被采纳。

QQ 交流群


QQ群号:721077608

微信公众号

支持我们!

为了更好地吸引和激励开发者,我们需要您的捐赠,帮助项目快速发展。

特别鸣谢!

感谢 JetBrains 公司的 IntelliJ IDEA 产品提供方便快捷的代码编辑和测试环境。

License

The Go-Spring is released under version 2.0 of the Apache License.

go-spring's People

Contributors

0width avatar 521274311 avatar acrossmountain avatar coderpoet avatar githublsl avatar limpo1989 avatar lkqm avatar llitfkitfk avatar lvan100 avatar sjsdfg avatar zundaren avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-spring's Issues

1.0.0 al版本无法初始化获取配置如何解决

原来的
SpringBoot.RegisterModule(func(ctx SpringCore.SpringContext) {
tmp := new(Gorm)
var err error
databaseType, ok := ctx.GetDefaultProperty("gorm.database", "postgres")
if !ok {

	}

tmp.DB, err = gorm.Open(databaseType.(string), conn_str)
if err != nil {
panic(err)
}
ctx.RegisterBean(tmp)

现在
init里面无法获取配置SpringBoot.RegisterBean(redisClient)。
因为想在SPRING注册里面实现加载配置测试连接是否成功

StaticFS设置问题

basepath=/vms
container.StaticFS("/static", http.FS(page.File))

首先这个静态路径没有拼接/vms前缀
正常这么访问http://localhost:8080/vms/static/1.jpg

//go:embed static favicon.ico index.html
var File embed.FS

比如我要访问static下的1.jpg, 上面的方式请求url会变成1.jpg,应该是static/1.jpg才能找到文件

是否支持html模板

没有找到像gin一样支持html模板: gctx.HTML(code, name, data) 简单的方式

目前实现比较麻烦, 需要自己注入Template,然后调用 tpl.ExecuteTemplate(webCtx.ResponseWriter, "index.html", data)

自定义类实现 Context 接口的话,有效率问题

官方的 context 包里有个 propagateCancel ,这里的逻辑是:
如果是 官方的几个context 类,那么直接找子节点做cancel
如果是 自定义的类,那么起个协程去做

SpringContext 嵌着一个 context.Context,但是,如果真的当作 context.Context 来用,代价是很高的,有考虑过这个问题吗?

go 1.15用官网示例,直接报错了。

go 1.15用官网示例,直接报错了。

E:\workspace\go\learn-go-spring>go run server.go
go: finding module for package github.com/go-spring/starter-echo
go: finding module for package github.com/go-spring/spring-boot
go: found github.com/go-spring/spring-boot in github.com/go-spring/spring-boot v1.0.5
go: found github.com/go-spring/starter-echo in github.com/go-spring/starter-echo v1.0.5


( ____ ( ___ ) ( ____ ( ____ )( ____ )__ /( ( /|( ____
| ( /| ( ) | | ( /| ( )|| ( )| ) ( | \ ( || ( /
| | | | | | _____ | (
___ | ()|| ()| | | | \ | || |
| | ____ | | | |()( )| )| ) | | | (\ ) || | ____
| | _ )| | | | ) || ( | (\ ( | | | | \ || | _ )
| (
) || (
) | /_
) || ) | ) \ _) (| ) \ || () |
(
)() _)|/ |/ _/_/|/ ))(_____)

               [email protected]    http://go-spring.com/

[ERROR] [email protected]/spring-context-default.go:617 fn should be func(context.Context, *struct})anything ↩
=> object bean "*main.Echo" E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-bean.go:841 ↩
panic: fn should be func(context.Context, *struct})anything [recovered]
panic: fn should be func(context.Context, *struct})anything

goroutine 1 [running]:
github.com/go-spring/spring-core.(*defaultSpringContext).AutoWireBeans.func1(0xc000bfd1a0)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-context-default.go:618 +0x168
panic(0x18d3700, 0xc000c70eb0)
D:/Go/src/runtime/panic.go:969 +0x176
github.com/go-spring/spring-web.BIND(0x18ae060, 0xc000c70ea0, 0x0, 0xc000bfd220)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-web-rpc.go:87 +0x2d1
github.com/go-spring/spring-boot.GetBinding(0x1997146, 0x1, 0x18ae060, 0xc000c70ea0, 0x0, 0x0, 0x0, 0x18b1a20)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-boot-web.go:423 +0x45
main.init.0.func1(0xc000c2fb40)
E:/workspace/go/learn-go-spring/server.go:10 +0x94
reflect.Value.call(0x18ae920, 0x19caf00, 0x13, 0x1997c1f, 0x4, 0xc000bfd1e0, 0x1, 0x1, 0x1, 0x0, ...)
D:/Go/src/reflect/value.go:475 +0x8e7
reflect.Value.Call(0x18ae920, 0x19caf00, 0x13, 0xc000bfd1e0, 0x1, 0x1, 0x0, 0x0, 0xc000c2fb40)
D:/Go/src/reflect/value.go:336 +0xc5
github.com/go-spring/spring-core.(*runnable).run(0xc00004c480, 0xc000bfd1a0, 0xc000bfab80, 0x0)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-configer.go:65 +0x1ee
github.com/go-spring/spring-core.(*defaultBeanAssembly).wireBeanDefinition(0xc000bfd1a0, 0x1a7f0c0, 0xc000bfab80, 0x26f1b00)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-bean-assembly.go:442 +0x6db
github.com/go-spring/spring-core.(*defaultSpringContext).wireBeans(0xc000d205a0, 0xc000bfd1a0)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-context-default.go:594 +0xc5
github.com/go-spring/spring-core.(*defaultSpringContext).AutoWireBeans(0xc000d205a0)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-context-default.go:623 +0x192
github.com/go-spring/spring-boot.(*application).Start(0xc000b005a0)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-boot-app.go:131 +0x15e
github.com/go-spring/boot-starter.Run(0x1a6e7e0, 0xc000b005a0)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/boot-starter.go:47 +0x86
github.com/go-spring/spring-boot.(*AppBuilder).Run(0xc000e1ff78, 0x0, 0x0, 0x0)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-boot-singlet.go:67 +0x20b
github.com/go-spring/spring-boot.RunApplication(...)
E:/GOPATH/pkg/mod/github.com/go-spring/[email protected]/spring-boot-singlet.go:72
main.main()
E:/workspace/go/learn-go-spring/server.go:23 +0x45
exit status 2

发展计划

有制订开发计划么?想了解一下,后续的发展方向

绑定接口不支持?

已解决
RT
type EventHandler interface {
OnNewConnect(c Connection)
OnNewRead(c Connection, readBuffer *ringbuffer.RingBuffer)
OnClose(c Connection)
}

type LwnetStarter struct {
Config *LwnetConfig autowire:""
eventHandle lwnet.EventHandler autowire:""
}

type LwnetServer struct {
A int
}

func (svr *LwnetServer) OnNewConnect(c lwnet.Connection) {
fmt.Println("OnNewConnect:" + c.RemoteAddr().String())
a := 1
_ = a
return
}

func (svr *LwnetServer) OnNewRead(c lwnet.Connection, ptBuff *ringbuffer.RingBuffer) {
fmt.Println("OnNewRead")
a := 1
_ = a
tmp_buf := make([]byte, ptBuff.Length())
ptBuff.Read(tmp_buf)
c.Write(tmp_buf)
return
}

func (svr *LwnetServer) OnClose(c lwnet.Connection) {
a := 1
_ = a
fmt.Println("OnClose")
return
}

这样注册这个BEAN,无法自动绑定,
错误panic: reflect: reflect.flag.mustBeAssignable using value obtained using unexported field

int 等基础类型的默认 bean 名称不对

v1.1.0-alpha 版本将 bean 的默认名称改为最简类型名,这种改进相比 type.string() 是有好处的,但是目前只处理了结构体指针类型 bean 的默认名称。

Ioc

spring使用Java注解扫描包完成bean定义、初始化、实例化、注册一系列操作;使用golang的哪个特性可以完成扫描那一步的操作?

ioc可以支持多例bean

看了源码,从目前ioc设计来看,对于bean只支持单例模式,但是对于某些有状态的依赖还是需要多例模式的支持

能否将controller中的路由通过swagger扫描自动加入到Route中

`
//菜单
type TestController struct {
}

// @title 获取所有菜单
// @description 获取所有菜单
// @param U-Token header string true "header.token"
// @param meta_title path string false "菜单名称"
// @success 200 {object} model.JsonReturn
// @failure 403 {string} string 查询错误
// @router /a [get]
func (c *TestController) GetAll(ctx SpringWeb.WebContext) {
ctx.JSON(200,model.JsonReturn{Name:"test"})
}

// @title 获取所有菜单
// @description 获取所有菜单
// @param body body model.TestModel true "菜单体"
// @success 200 {object} model.JsonReturn
// @failure 403 {string} string 查询错误
// @router /b [get]
func (c *TestController) GetOne(ctx SpringWeb.WebContext) {
ctx.JSON(200,model.JsonReturn{Name:"test"})
}`

v1 := SpringBoot.Route("/api", &filter.ApiFilter{}).Route("/v1") v1.HandleController(&controller.TestController{})

类似这种通过controller对象扫描所有的路由

Go-Spring 核心原理 (上) 一文中

func main() {

springContext := SpringCore.NewSpringContext()

app := new(Application)
springContext.RegisterBean(app)

cfg := &Config{Name: "Jim"}
springContext.RegisterBean(cfg)

ds := &DataSource{
Url: "jdbc:mysql:127.0.0.1...",
}

springContext.RegisterBean(ds)
//springContext.RegisterNameBean("ds", ds) // 这一行!

springContext.AutoWireBeans()

b, _ := json.MarshalIndent(app, "", " ")
fmt.Println(string(b))
}

SpringCore包没有这个NewSpringContext()方法

启动SpringBoot不对主协程进行阻塞

对于已有系统,想集成Go-Spring,但已有系统已有Http服务,并在Http服务启动后,将会对主协程进行阻塞;若集成了Go-Spring后,但却暂时未把原有的Http服务转用Go-Spring来构建的情况下,不好集成。因为GO-Spring的SpringBoot启动也是阻塞的;期望提供启动SpirngBoot但不阻塞主协程的使用方式

能否考虑将 checkCondition 从 autoWireBeans 抽到 register 中

比如某两个 bean 的存在根据某些条件互斥, 但必定存在其中一个。
同是又存在同类型的其他 bean 导致无法按类型注入。
这时候注册两个同名同类型且存在条件互斥的 bean 应该是合理的

假设一场景:
生产环境 redis 分为持久化集群与非持久化集群, 但测试环境仅有一套。
有 demo 如下:

type Service struct {
	RedisStore *Redis `autowire:"storeRedis"` //持久化集群, primary
	RedisCache *Redis `autowire:"cacheRedis"` // 仅缓存集群
}
func main() {
	context := SpringCore.DefaultApplicationContext()
	testEnvCondition := SpringCore.NewPropertyValueCondition("env", "testing")
	context.RegisterBeanDefinition(
		SpringCore.ObjectBean(NewStoreRedis).Primary(true).
			// 正式环境可用 持久化 集群
			ConditionNot(testEnvCondition).
			WithName("storeRedis"))
	context.RegisterBeanDefinition(
		// 测试环境 持久化集群不可用, 业务逻辑上使用个壳子替代其 bean 定义
		SpringCore.ObjectBean(NewFakeRedis).Primary(true).
			ConditionNot(testEnvCondition).
                        //但是要求同名
			WithName("storeRedis"))
	context.RegisterNameBeanFn("cacheRedis", NewCacheRedis)
}

目前这段是肯定会报 「duplicate registration」,如果能将 checkCondition 提取到注册时, 不满足直接不注册了就会舒服很多。

我理解当初这么设计可能是因为没有把启动流程控死, 可能是 SetProperty 和 RegisterBean 这两块没有严格顺序?
是否有希望可以调整呢?

关于XxxMapping方法和XxxBinding方法合并

在使用XxxBinding过程中发现这个方法限制比较多(2个入参,1个返回参数), 查看源码发现XxxMapping可以和XxxBinding合并:

router.go

原方法:

func (r *router) RequestMapping(method uint32, path string, fn HandlerFunc) *Mapper {
	return r.request(method, path, FUNC(fn))
}

修改后:

func (r *router) RequestMapping(method uint32, path string, fn interface{}) *Mapper {
	var handler Handler
	if f, ok := fn.(func(ctx web.Context)); ok {
		handler = FUNC(f)
	} else if f, ok := fn.(func(http.ResponseWriter, *http.Request)); ok {
		var hf http.HandlerFunc = f
		handler = httpFuncHandler(hf)
	} else {
		handler = BIND(fn)
	}
	return r.request(method, path, handler)
}

另外XxxBinding的处理方法限制条件有些多, 参数和返回值尽可能宽松,这样才能符合使用习惯

Not support complex data types when parsing yaml files

yaml file

application:
  dbs:
    -
      uname: root1
      pwd: 123456
      url: 1.1.1.1
      port: 3306
      dbname: p1
    -
      uname: root2
      pwd: 1212
      url: 1.1.1.1
      port: 3306
      dbname: data

struct

type Db struct {
	Uname  string `value:"${uname}"`
	Pwd    string `value:"${pwd}"`
	Url    string `value:"${url}"`
	Port   string `value:"${port}"`
	Dbname string `value:"${dbname}"`
}
type Config struct {
	Dbs      []Db     `value:"${application.dbs}"`
}

reslut

register bean pigeonProgram/pgCommon/config/config.Config:*config.Config
wire bean pigeonProgram/pgCommon/config/config.Config:*config.Config
--- FAIL: TestPgServerDao_GetPgServerDao (0.00s)
panic: Config.$Dbs unsupported type slice [recovered]
        panic: Config.$Dbs unsupported type slice

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.