美文网首页GO与微服务
手撸golang 仿spring ioc/aop 之5 如何扫描

手撸golang 仿spring ioc/aop 之5 如何扫描

作者: 老罗话编程 | 来源:发表于2021-04-13 16:55 被阅读0次

    手撸golang 仿spring ioc/aop 之5 如何扫描

    缘起

    最近阅读 [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 5)

    • Q:搞点啥?
    • A:扫描go代码文件
    • Q:具体点?
    • A:递归扫描指定的目录下所有go代码,并提取结构体,字段,方法和注解信息
    • Q:什么思路?
    • A:
        1. 读取go文件>解析package>解析import>解析struct列表>解析field列表>解析method列表
        1. 逐struct,解析注解
        1. 逐field,解析注解
        1. 逐method,解析注解
    • Q:如何解析?
    • A:读取文本>清除注释>逐行正则扫描
    • Q:清除注释?
    • A:因为注释里面可以写任何东西,所以清除注释后可以减少解析错误的可能
    • Q:如何清除?
    • A:
      • LINE_COMMENT = '//' [^\r\n]*
      • PARA_COMMENT = '/' . '*/'
    • Q:扫描package?
    • A:PACKAGE = ‘package' SPACE+ \w+
    • Q:扫描import?
    • A:
      • SINGLE_IMPORT = 'import' SPACE+ PACKAGE_LITERAL
      • PACKAGE_LITERAL = (PACKAGE_ALIAS SPACE+)? "\w+(/\w+)*"
      • MULTI_IMPORT = 'import' SPACE+ '(\r\n' (SPACE* PACKAGE_LITERAL)+ '\r\n)'
    • Q:扫描struct?
    • A:
      • STRUCT_START = 'type' SPACE+ \w+ SPACE+ 'struct' SPACE+ '{'
      • STRUCT_END = '}'
    • Q:扫描field?
    • A:
      • STRUCT_FIELD = SPACE+ \w+ FIELD_TYPE
      • FIELD_TYPE = BASIC_TYPE | CUSTOM_TYPE | POINTER_TYPE | ARRAY_TYPE | MAP_TYPE
      • BASIC_TYPE = 'int' | 'string' | 'bool' | ’uint‘ | 'rune' | 'byte' | 'int8' | 'uint8' | 'int16' | 'uint16' | 'int32' | 'uint32' | 'int64' | 'uint64' | 'float32' | 'float64'
      • CUSTOM_TYPE = (PACKAGE_ALIAS.)?\w+
      • POINTER_TYPE = '*' FIELD_TYPE
      • ARRAY_TYPE = '[]' FIELD_TYPE
      • MAP_TYPE = 'map[' FIELD_TYPE ']' FIELD_TYPE
    • Q:扫描method?
    • A:
      • METHOD_START = 'func' SPACE+ RECEIVER METHOD_ARGS METHOD_RETURNS? '{'
      • RECEIVER = '(' RECEIVER_VAR *? RECEIVER_TYPE ')'
      • RECEIVER_VAR = \w+
      • RECEIVER_TYPE = \w+
      • METHOD_ARGS = '(' SPACE* METHOD_ARG? (SPACE* ',' SPACE* METHOD_ARG)* ')'
      • METHOD_ARG = \w+ SPACE* FIELD_TYPE
      • RETURNS = SINGLE_RETURN | MULTI_RETURN
      • SINGLE_RETURN = FIELD_TYPE
      • METHOD_RETURNS = '(' SPACE* RETURN_ARG? (SPACE* ',' SPACE* RETURN_ARG)* ')'
      • RETURN_ARG = NAMED_RETURN_ARG | UNNAMED_RETURN_ARG
      • NAMED_RETURN_ARG = \w+ SPACE* FIELD_TYPE
      • UNNAMED_RETURN_ARG = FIELD_TYPE
    • Q:提取注解?
    • A:
      • 提取指定struct/field/method之前的连续注释行
      • 提取 '// @'开头的注释 认为是注解行
      • 提取具体注解
        • ANNOTATION = '@' \w+ (SPACE+ ANNOTATION_ATTRIBUTE+)?
        • ANNOTATION_ATTRIBUTE = AA_KEY '=' AA_VALUE
        • AA_KEY = \w+
        • AA_VALUE = [^\w,]+

    (未完待续)

    相关文章

      网友评论

        本文标题:手撸golang 仿spring ioc/aop 之5 如何扫描

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