溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何用golang仿spring ioc/aop編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器

發(fā)布時間:2021-10-14 11:53:41 來源:億速云 閱讀:135 作者:iii 欄目:編程語言

這篇文章主要講解了“如何用golang仿spring ioc/aop編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“如何用golang仿spring ioc/aop編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器”吧!

Spring

Spring基于J2EE技術(shù)實現(xiàn)了一套輕量級的
Java Web Service系統(tǒng)應(yīng)用框架。
它有很多優(yōu)秀的特性,很多公司都選擇把
Spring作為產(chǎn)品或項目的基礎(chǔ)開發(fā)架構(gòu)。

Spring的主要特性包括:
1. 輕量
2. 控制反轉(zhuǎn)(Inversion of Control, IoC)
3. 面向容器
4. 面向切面(AspectOriented Programming, AOP)
5. 框架靈活

源碼gitee地址:
https://gitee.com/ioly/learning.gooop

原文鏈接:
https://my.oschina.net/ioly

目標(biāo)

  • 參考spring常用注解,使用golang編寫“基于注解的靜態(tài)代碼增強(qiáng)器/生成器”

    • 配置: ComponentScan,Configuration, Bean

    • Bean聲明:Component, Service, Controller

    • Bean注入:Autowried

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

子目標(biāo)(Day 3)

  • 添加ProjectCmd以支持項目定義

  • 添加文本掃描的輔助類:Chars.go, Tokens.go

  • 定義代碼生成服務(wù)接口ICodingService及其支撐接口

設(shè)計

  • command/ProjectCmd: 項目定義指令

  • common/Chars: 字符識別輔助類

  • common/Tokens: 組合文本識別輔助類

  • service/ICodingService: 代碼生成服務(wù)接口

  • service/iCodingContext: 代碼生成上下文

  • service/iCodingState:狀態(tài)模式下的服務(wù)狀態(tài)

  • service/iCmdRunner:定義指令執(zhí)行器接口,具體執(zhí)行擬走責(zé)任鏈模式以便擴(kuò)展

  • service/tInitialState:默認(rèn)的服務(wù)狀態(tài)

command/ProjectCmd.go

項目定義指令

package project_cmd

import (
	"errors"
	"fmt"
	"learning/gooop/spring/autogen/command"
	"learning/gooop/spring/autogen/common"
	"os"
	"strings"
)

// ProjectCmd defines a project with name and dir
type ProjectCmd struct {
	name string
	dir string
}

// ProjectCmdBuilder parses cli input and creates a ProjectCmd instance
type ProjectCmdBuilder int

const gProjectCmdPrefix = "project "
var gErrorInvalidProjectCmd = errors.New("invalid project cmd")

func (me *ProjectCmd) String() string {
	return fmt.Sprintf("project %s %s", me.name, me.dir)
}

func (me *ProjectCmd) Apply(ctx command.ICmdContext) error {
	panic("implements me")
}

func (me *ProjectCmdBuilder) Build(line string) (error, command.ICmd) {
	if !common.Tokens.MatchString(line, gProjectCmdPrefix) {
		return nil, nil
	}

	line = strings.TrimSpace(line[len(gProjectCmdPrefix):])
	b,name := common.Tokens.MatchIdentifier(line)
	if !b {
		return gErrorInvalidProjectCmd, nil
	}

	line = line[len(name):]
	b, spaces := common.Tokens.MatchSpaces(line)
	if !b {
		return gErrorInvalidProjectCmd, nil
	}

	line = line[len(spaces):]
	b, dir := common.Tokens.MatchDir(line)
	if !b {
		return gErrorInvalidProjectCmd, nil
	}
	_,e := os.Stat(dir)
	if e != nil {
		return e, nil
	}

	return nil, &ProjectCmd{ name, dir }
}

common/Chars.go

字符識別輔助類

package common


type tChars int

var Chars = new(tChars)

func (me *tChars) IsSpace(it rune) bool {
	switch it {
	case ' ':
		return true
	case '\t':
		return true
	case '\r':
		return true
	case '\n':
		return true
	}

	return false
}


func (me *tChars) Is09(it rune) bool {
	return it >= '0' && it <= '9'
}

func (me *tChars) Is19(it rune) bool {
	return it >= '1' && it <= '9'
}

func (me *tChars) IsLetter(it rune) bool {
	return (it >= 'a' && it <= 'z') || (it >= 'A' && it <= 'Z')
}

func (me *tChars) IsUnderscore(it rune) bool {
	return it == '_'
}

func (me *tChars) IsLB(it rune) bool {
	return it == '('
}

func (me *tChars) IsRB(it rune) bool {
	return it == ')'
}

func (me *tChars) IsChar(it rune, args... rune) bool {
	for _,v := range args {
		if v == it {
			return true
		}
	}
	return false
}

func (me *tChars) IsSQuote(it rune) bool {
	return me.IsChar(it, '\'')
}

func (me *tChars) IsDQuote(it rune) bool {
	return me.IsChar(it, '"')
}

func (me *tChars) IsRSplash(it rune) bool {
	return me.IsChar(it, '\\')
}

func (me *tChars) IsLSplash(it rune) bool {
	return me.IsChar(it, '/')
}

common/Tokens.go

組合文本識別輔助類

package common

import (
	"regexp"
	"strings"
	"sync"
)

type tTokens struct {
	cache map[string]*regexp.Regexp
	rwmutex *sync.RWMutex
}

var Tokens = newTokensLib()

func newTokensLib() *tTokens {
	it := new(tTokens)
	it.init()
	return it
}

func (me *tTokens) init() {
	me.cache = make(map[string]*regexp.Regexp)
	me.rwmutex = new(sync.RWMutex)
}

func (me *tTokens) MatchString(s string, p string) bool {
	return strings.HasPrefix(s, p)
}

func (me *tTokens) MatchRegexp(s string, p string) (bool, string) {
	me.rwmutex.RLock()
	r,ok := me.cache[p]
	me.rwmutex.RUnlock()

	if !ok {
		me.rwmutex.Lock()
		if r,ok = me.cache[p];!ok {
			r,_ = regexp.Compile(p)
		}
		me.rwmutex.Unlock()
	}

	if r == nil {
		return false, ""
	}

	if !r.MatchString(s) {
		return false, ""
	}

	return true, r.FindString(s)
}

func (me *tTokens) MatchIdentifier(s string) (bool, string) {
	return me.MatchRegexp(s, "^[_a-zA-Z]\\w{0,99}}")
}

func (me *tTokens) MatchSpaces(s string) (bool, string) {
	return me.MatchRegexp(s, "^\\s+")
}

func (me *tTokens) MatchDir(s string) (bool, string) {
	b,s := me.MatchRegexp(s, "^([a-zA-Z]\\:)?([\\\\/][^\\s/:*?<>|\\\"\\\\]+)+[\\/]?")
	if b {
		return b,s
	}

	b,s = me.MatchRegexp(s, "^\\\"([a-zA-Z]\\:)?([\\\\/][^/:*?<>|\\\"\\\\]+)+[\\/]?\\\"")
	if b {
		return b,s
	}

	b,s = me.MatchRegexp(s, "^'([a-zA-Z]\\:)?([\\\\/][^'/:*?<>|\\\"\\\\]+)+[\\/]?'")
	if b {
		return b,s
	}

	return false, ""
}

service/ICodingService.go

代碼生成服務(wù)接口

package service

type ICodingService interface {
	iCmdRunner

	State() iCodingState
	Start()
}

service/iCodingContext.go

代碼生成上下文

package service

// iCodingContext provides context info for iCodingState instance
type iCodingContext interface {
	HandleStateChanged(state iCodingState)
}

service/iCodingState.go

狀態(tài)模式下的服務(wù)狀態(tài)

package service

type iCodingState interface {
	iCmdRunner
}

service/iCmdRunner.go

定義指令執(zhí)行器接口,具體執(zhí)行擬走責(zé)任鏈模式以便擴(kuò)展

package service

import "learning/gooop/spring/autogen/command"

// iCmdRunner runs a user cmd
type iCmdRunner interface {
	Run(cmd command.ICmd) error
}

service/tInitialState.go

默認(rèn)的服務(wù)狀態(tài)

package service

import (
	"errors"
	"learning/gooop/spring/autogen/command"
)

// tInitialState is the default state for a coding service
// it will only accept ProjectCmd
type tInitialState struct {
	context iCodingContext
}

func newInitialState(c iCodingContext) iCodingState {
	it := new(tInitialState)
	it.init(c)
	return it
}

func (me *tInitialState) init(c iCodingContext) {
	me.context = c
}

var gErrorProjectDefineRequired = errors.New("project not defined: project <name> <dir>")


func (me *tInitialState) Run(cmd command.ICmd) error {
	panic("implement me")
}

感謝各位的閱讀,以上就是“如何用golang仿spring ioc/aop編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對如何用golang仿spring ioc/aop編寫基于注解的靜態(tài)代碼增強(qiáng)器/生成器這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

go
AI