我正在尝试使用芭蕾舞演员(在MacOS Catalina上为jBallerina-1.0.5)实现一个简单的注释处理器。在此示例中,我需要:

  • 遍历给定resource的可用service函数
  • 对于每次迭代,获取给定的@annotation的值,如resource所示

  • 例如:
    ...
    service my_service on new http:Listener(8080) {
        @my_annonatation {
            value: "my-value-for-resource-1"
        }
        resource function my_resource_1() {}
    
        @my_annonatation {
            value: "my-value-for-resource-2"
        }
        resource function my_resource_2() {}
    }
    

    根据上面的service代码片段,我需要将resource名称作为["my_resource_1", "my_resource_2"],将@annotation值作为my-value-for-resource-1,将my-value-for-resource-2分别用于my_resource_1my_resource_2

    我的问题是:
  • 如何使用芭蕾舞女演员
  • 获取在给定resource中定义的service
  • 我已经尝试使用function getServiceAnnotations(service serviceType, string annotName, string? moduleName = ()) returns any模块的ballerina/reflect来获取@annotation值。但是它没有任何回报(显然,它返回一个空字符串或可以为null)。

  • 除了旧的芭蕾舞女演员0.x预发行版1之外,我没有看到任何有关芭蕾舞女演员注释处理的好文章。我发现ballerina/reflect模块现在已更新2 3,因为我将其与芭蕾舞女演员源代码进行了比较(但未在芭蕾舞女演员发行说明4中提及),因为0.x预发布。

    另外,文章“扩展芭蕾舞演员” 5提到了通过编译器扩展进行注解处理的另一种方法,该扩展将操作委托给Java。但是,我们存在将Java依赖关系推入ballerina central的限制。

    请向我建议一种解决方法,以获得期望的结果,并且非常感谢纯芭蕾舞演员编写的代码。

    参考
  • Ballerina Annotation Processing example for 0.9.x releases
  • ballerina/reflect of 0.x
  • ballerina/reflect of 1.0.5
  • Ballerina release notes
  • Extending Ballerina
  • 最佳答案

    注释处理可以在编译时或运行时进行。目前(使用Ballerina 1.0.5和更早版本),编译时注释处理只能通过“扩展芭蕾舞女演员”文档中所述的编译器扩展来完成,而运行时注释访问可以使用annotation access expressionballerina/reflect完成模块(在ballerina/reflect模块中仅提供了通过注释访问表达式无法实现的模块-尽管在发行说明“已引入二进制运算符。@以便在运行时访问注释值”中提到了这一点)。这样就从ballerina/reflect模块中删除了一些功能,似乎已经错过了)。

    https://github.com/ballerina-platform/ballerina-lang/issues/19325描述了拟议的Ballerina编译器插件体系结构,该体系结构允许在Ballerina中编写扩展。

    在运行时:

  • 检索服务中定义的资源的名称-IINM,如果不编写外部方法(使用Java互操作),当前无法实现。在编译时是否不知道资源名称?您能否根据要求创建一个issue in the ballerina-lang repository
  • 访问资源注释-可以使用reflect:getResourceAnnotations方法
  • 完成
    import ballerina/http;
    import ballerina/io;
    import ballerina/reflect;
    
    type AnnotRecord record {|
        string value;
    |};
    
    annotation AnnotRecord my_annonatation on resource function;
    
    string[] resourceNames = ["my_resource_1", "my_resource_2"];
    
    service my_service on new http:Listener(8080) {
        @my_annonatation {
            value: "my-value-for-resource-1"
        }
        resource function my_resource_1(http:Caller caller, http:Request request) {}
    
        @my_annonatation {
            value: "my-value-for-resource-2"
        }
        resource function my_resource_2(http:Caller caller, http:Request request) {}
    }
    
    public function main() {
        foreach var resourceName in resourceNames {
            any annot = reflect:getResourceAnnotations(my_service, resourceName, "my_annonatation");
            if annot is AnnotRecord {
                io:println(annot.value);
            }
        }
    }
    

    10-04 21:04