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

Posted ioly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手撸golang 仿spring ioc/aop 之5 如何扫描相关的知识,希望对你有一定的参考价值。

手撸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 = \'//\' 1*
    • 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 = 2+

(未完待续)


  1. \\r\\n ↩
  2. \\w, ↩

以上是关于手撸golang 仿spring ioc/aop 之5 如何扫描的主要内容,如果未能解决你的问题,请参考以下文章

手撸golang 仿spring ioc/aop 之11 增强2

手撸golang 仿spring ioc/aop 之8 扫码3

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

手撸golang 仿spring ioc/aop 之7 扫码2

手撸golang 仿spring ioc/aop 之3

手撸golang spring ioc/aop 之2