美文网首页GO与微服务
手撸golang 仿spring ioc/aop 之4 蓝图

手撸golang 仿spring ioc/aop 之4 蓝图

作者: 老罗话编程 | 来源:发表于2021-04-12 18:22 被阅读0次

    手撸golang 仿spring ioc_aop 之4 蓝图

    缘起

    最近阅读 [Spring Boot技术内幕: 架构设计与实现原理] (朱智胜 , 2020.6)
    本系列笔记拟采用golang练习之
    Talk is cheap, show me the code.

    Spring

    Spring的主要特性:
    1. 控制反转(Inversion of Control, IoC)
    2. 面向容器
    3. 面向切面(AspectOriented Programming, AOP)
    
    源码gitee地址:
    https://gitee.com/ioly/learning.gooop
    
    原文链接:
    https://my.oschina.net/ioly
    

    目标

    • 参考spring常用注解,使用golang编写“基于注解的静态代码增强器/生成器”
      • 配置: ComponentScan,Configuration, Bean

      • Bean声明:Component, Service, Controller

      • Bean注入:Autowried

      • AOP注解:Before, After, Around, PointCut

    子目标(Day 4)

    • 前两天都是在整外围接口,没说清楚到底要搞啥
    • 今天以@RestController为例,把项目目标理清楚:
      • 以gin框架为基础,描述一个订单CRUD服务
      • 以@RestController为例,手写增强前后的代码,描绘如何增强
      • 增强前,应当尽可能简洁,降低框架侵入性
      • 增强后,与框架很好的结合,把脏活累活默默干好

    设计

    • OrderController: 订单服务控制器
    • OrderController_Enhanced:增强后的订单服务控制器
      • 添加SetOrderService方法以便依赖注入
      • 添加xxx_Enhanced方法,以集成到gin框架
      • 添加RegisterRestController方法,以注册到Bean容器
      • 添加init()方法,以便Bean容器引用
    • IOrderService:订单持久化服务接口
    • MockOrderService:订单持久化服务的实现,码略
    • dto/, entity/: 订单服务的实体类和数值类,码略
    • IBeanRegistry:bean注册表接口
    • IRestController:RESTFul控制器接口
    • IControllerRegistry:RESTFul控制器注册表及其默认实现

    OrderController.go

    订单服务控制器

    package controller
    
    import (
        "learning/gooop/spring/demo/order/dto"
        "learning/gooop/spring/demo/order/entity"
        "learning/gooop/spring/demo/order/service"
    )
    
    // OrderController handles rest requests for CRUD orders
    // @RestController
    // @RequestMapping path=/order
    type OrderController struct {
        orderService service.IOrderService
    }
    
    // Save create or update an order
    // @PostMapping
    func (me *OrderController) Save(head *entity.OrderHeadEntity, items []*entity.OrderItemEntity) error {
        return me.orderService.Save(head, items)
    }
    
    // View gets order and order items
    // @GetMapping
    func (me *OrderController) View(orderID int) (error, *dto.OrderDTO) {
        return me.orderService.Get(orderID)
    }
    
    // Query query order headers by custom conditions
    // @GetMapping
    func (me *OrderController) Query(customerID int, statusFlag int, dateFrom string, dateTo string, pageNO int, pageSize int) (error, []*dto.OrderHeadDTO) {
        return me.orderService.Query(customerID, statusFlag, dateFrom, dateTo, pageNO, pageSize)
    }
    

    OrderController_Enhanced.go

    增强后的订单服务控制器

    • 添加SetOrderService方法以便依赖注入
    • 添加xxx_Enhanced方法,以集成到gin框架
    • 添加RegisterRestController方法,以注册到Bean容器
    • 添加init()方法,以便Bean容器引用
    package controller
    
    import (
        "github.com/gin-gonic/gin"
        "learning/gooop/spring/demo/framework/bean/controller"
        "learning/gooop/spring/demo/order/dto"
        "learning/gooop/spring/demo/order/entity"
        "learning/gooop/spring/demo/order/service"
        "net/http"
    )
    
    // OrderController_Enhanced handles rest requests for CRUD orders
    // @RestController
    // @RequestMapping path=/order
    type OrderController_Enhanced struct {
        // @Autowired
        orderService service.IOrderService
    }
    
    // SetOrderService is auto generated setter method for injecting service.IOrderService into me.orderService
    func (me *OrderController_Enhanced) SetOrderService(it interface{}) {
        me.orderService = it.(service.IOrderService)
    }
    
    // Save create or update an order
    // @PostMapping
    func (me *OrderController_Enhanced) Save(head *entity.OrderHeadEntity, items []*entity.OrderItemEntity) error {
        return me.orderService.Save(head, items)
    }
    
    // OrderController_Save_ParamsDTO is auto generated struct for wrapping parameters of OrderController.Save
    type OrderController_Save_ParamsDTO struct {
        Order *entity.OrderHeadEntity
        Items []*entity.OrderItemEntity
    }
    
    // View_Enhanced is the enhanced version of Save
    func (me *OrderController_Enhanced) Save_Enhanced(c *gin.Context) {
        r := new(OrderController_Save_ParamsDTO)
        e := c.BindJSON(r)
        if e != nil {
            c.JSON(http.StatusBadRequest, gin.H{"ok": false, "error": e.Error()})
            return
        }
    
        e = me.Save(r.Order, r.Items)
        if e != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"ok": false, "error": e.Error()})
            return
        }
    
        c.JSON(http.StatusOK, gin.H{"ok": true})
    }
    
    // View gets order and order items
    // @GetMapping
    func (me *OrderController_Enhanced) View(orderID int) (error, *dto.OrderDTO) {
        return me.orderService.Get(orderID)
    }
    
    // View_Enhanced is the enhanced version of View
    func (me *OrderController_Enhanced) View_Enhanced(c *gin.Context) {
        id := c.GetInt("id")
        e, d := me.View(id)
        if e != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"ok": false, "error": e.Error()})
        }
    
        c.JSON(http.StatusOK, d)
    }
    
    // Query query order headers by custom conditions
    // @GetMapping
    func (me *OrderController_Enhanced) Query(customerID int, statusFlag int, dateFrom string, dateTo string, pageNO int, pageSize int) (error, []*dto.OrderHeadDTO) {
        panic("implements me")
    }
    
    // OrderController_Query_ParamsDTO is auto generated struct for wrapping parameters of PagedQuery
    type OrderController_Query_ParamsDTO struct {
        CustomerID int
        StatusFlag int
        DateFrom   string
        DateTO     string
        PageNO     int
        PageSize   int
    }
    
    // Query_Enhanced is the enhanced version of PagedQuery
    func (me *OrderController_Enhanced) Query_Enhanced(c *gin.Context) {
        r := new(OrderController_Query_ParamsDTO)
        e := c.Bind(r)
        if e != nil {
            c.JSON(http.StatusBadRequest, gin.H{"ok": false, "error": e.Error()})
            return
        }
    
        e, d := me.Query(r.CustomerID, r.StatusFlag, r.DateFrom, r.DateTO, r.PageNO, r.PageSize)
        if e != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"ok": false, "error": e.Error()})
            return
        }
    
        c.JSON(http.StatusOK, gin.H{"ok": true, "data": d})
    }
    
    // RegisterRestController is auto generated to implements controller.IRestController interface
    func (me *OrderController_Enhanced) RegisterRestController(r *gin.Engine) {
        r.POST("/order/save", me.Save_Enhanced)
        r.GET("/order/view", me.View_Enhanced)
        r.GET("/order/query", me.Query_Enhanced)
    }
    
    // init is auto generated to register OrderController_Enhanced into controller.ControllerRegistry
    func init() {
        it := new(OrderController_Enhanced)
        controller.ControllerRegistry.Register(it)
    }
    

    IOrderService.go

    订单持久化服务接口

    package service
    
    import (
        "learning/gooop/spring/demo/order/dto"
        "learning/gooop/spring/demo/order/entity"
    )
    
    type IOrderService interface {
        Save(head *entity.OrderHeadEntity, items []*entity.OrderItemEntity) error
        Get(orderID int) (error, *dto.OrderDTO)
        Query(customerID int, statusFlag int, dateFrom string, dateTo string, pageNO int, pageSize int) (error, []*dto.OrderHeadDTO)
    }
    

    IBeanRegistry.go

    bean注册表接口

    package bean
    
    type IBeanRegistry interface {
        All() []interface{}
    }
    

    IRestController.go

    RESTFul控制器接口

    package controller
    
    import "github.com/gin-gonic/gin"
    
    type IRestController interface {
        RegisterRestController(r *gin.Engine)
    }
    

    IControllerRegistry.go

    RESTFul控制器注册表及其默认实现

    package controller
    
    import (
        "github.com/gin-gonic/gin"
        "learning/gooop/spring/demo/framework/bean"
        "sync"
    )
    
    type IControllerRegistry interface {
        bean.IBeanRegistry
    
        Register(it IRestController)
        Apply(r *gin.Engine)
    }
    
    type tDefaultControllerRegistry struct {
        rwmutex *sync.RWMutex
        items   []IRestController
    }
    
    func (me *tDefaultControllerRegistry) All() []interface{} {
        me.rwmutex.RLock()
        defer me.rwmutex.RUnlock()
    
        all := make([]interface{}, len(me.items))
        for i, it := range me.items {
            all[i] = it
        }
        return all
    }
    
    func (me *tDefaultControllerRegistry) Register(it IRestController) {
        me.rwmutex.Lock()
        defer me.rwmutex.Unlock()
    
        me.items = append(me.items, it)
    }
    
    func (me *tDefaultControllerRegistry) Apply(r *gin.Engine) {
        me.rwmutex.RLock()
        defer me.rwmutex.RLock()
    
        for _, it := range me.items {
            it.RegisterRestController(r)
        }
    }
    
    func newDefaultControllerRegistry() IControllerRegistry {
        return &tDefaultControllerRegistry{
            new(sync.RWMutex),
            []IRestController{},
        }
    }
    
    var ControllerRegistry = newDefaultControllerRegistry()
    

    (未完待续)

    相关文章

      网友评论

        本文标题:手撸golang 仿spring ioc/aop 之4 蓝图

        本文链接:https://www.haomeiwen.com/subject/umnxlltx.html