0

附录编辑:

由于没有经验丰富的 Spring Framework 开发人员的任何反馈,因此尚未接受对此的回答。

我一直在研究用于 Spring-Framework applicationContext.xml 文件的替代 DSL(其中描述了 bean 初始化和依赖关系以加载到 Spring bean 工厂中)。

我的动机是我完全不喜欢 Spring 为此目的使用 XML,也不喜欢迄今为止设计的任何替代方案。出于各种我不会深入讨论的原因,我想继续使用声明性语言,而不是像 Groovy 这样的命令式脚本语言。

所以我抓住了 ANTLR 解析器工具,并一直在设计一个新的 bean factory DSL,我称之为 SFig。这是一个有关此内容的链接:

SFig™ - Spring-Framework 的替代元数据配置语言

这是源代码存储库站点:

http://code.google.com/p/sfig/

我很想知道到目前为止我在语言语法上的表现如何。您认为 SFig 既高效又清晰易懂?(我现在特别关心多行文本字符串):

properties_include "classpath:application.properties";


org.apache.commons.dbcp.BasicDataSource dataSource {
    @scope = singleton;
    @destroy-method = close;
    driverClassName = "${jdbc.driverClassName}";
    url = "${jdbc.url}";
    username = "${jdbc.username}";
    password = "${jdbc.password}";
    defaultAutoCommit = true;
}


org.springframework.orm.ibatis.SqlMapClientFactoryBean sqlMapClient {
    @scope = singleton;
    @init-method = afterPropertiesSet;
    @factory-method = getObject;
    configLocation = "classpath:sqlmap-config.xml";
    dataSource = $dataSource;
}


/* this string will have Java unescape encoding applied */
STRING str = "\tA test\u0020string with \\ escaped character encodings\r\n";


/* this string will remain literal - with escape characters remaining in place */
STRING regexp = @"(\$\{([a-zA-Z][a-zA-Z0-9._]*)\})";


/* multi-line text block - equates to a java.lang.String instance */
TEXT my_multi_line_text = ///
Here is a line of text.
This is yet another. Here is a blank line:

Now picks up again.
///;


/* forward use of 'props' bean */
java.util.HashMap map {
    this( $props );
}


/* equates to a java.util.Propertis instance */
PROPERTIES props {
    "James Ward" = "Adobe Flex evangelist";
    "Stu Stern" = "Gorilla Logic - Flex Monkey test automation";
    Dilbert = "character in popular comic strip of same title";
    "App Title Display" = "Application: ${app.name}";
    "${app.desc}" = "JFig processes text-format Java configuration data";
}


/* equates to a java.util.ArrayList instance */
LIST list {
    this( ["dusty", "moldy", "${app.version}", $str] );
    [234, 9798.76, -98, .05, "numbers", $props, ["red", "green", "blue"]];
}
4

2 回答 2

0

我对您引用的 Spring XML 没有太多经验,因此您应该对以下反馈有所了解。

作为第二和第三个警告:

  • 提供一段代码将使您了解该语言及其语义。很难完全理解您已经做出的一些选择(并且有充分的理由),因此根据这些选择,这里的任何反馈都可能完全矛盾或不可能。
  • 语言设计既是一门艺术,也是一门科学,因此在这个阶段,你可能得到的任何反馈都可能是相当主观的。

一个更大的元问题:作为 DSL,您是在尝试配置 Spring,还是作为更通用的框架类?

那里:警告购买者。现在我的主观和不完整的反馈;)

  • 我不确定我理解为什么你有@前缀的原因scopeand destroy-method,但没有driverClassName。此外,xml-case 和 camelCase的混合在开始时并不完全明显。前缀是@类型修饰符,还是语言中的这些关键字?

  • 我不完全确定您对块头格式的意图。您有类名,然后是该类的函数;是否打算指定您将为特定功能使用的类?

例如

sqlMapClient: org.springframework.orm.ibatis.SqlMapClientFactoryBean {
    # body.
}

甚至:

sqlMapClient {
    @class = org.springframework.orm.ibatis.SqlMapClientFactoryBean;
    # is there a sensible (perhaps built-in) default if this is missing?
}
  • 我喜欢变量替换;我认为这些值将来自系统属性?

  • 我喜欢能够指定字符串文字(无需转义),尤其是对于您展示的正则表达式。但是,使用多字符引号或引号修饰符似乎有点陌生。我猜你考虑过单引号(shell 和 Perl 对文字字符串使用单引号)。

  • 另一方面,我认为多行TEXT的三个正斜杠是正确的方法,但两个让人想起 C 风格语言中的注释。"为此,Python 使用了三元组。一些 shell 习语有一个我不会复制的多行文本约定。

  • 我非常喜欢属性和配置位置的外观,使用看起来像寻址的 URI 概念。如果这是一个URI,classpath://file.xml可能会更清楚。然而,我在这里可能有错误的一端。

  • 我也非常喜欢您拥有的列表和映射文字的概念,尽管我不确定在哪里:

    • this进入它(我猜是对Java构造函数的调用)
    • 为什么有些类型是大写的,而另一些不是。我是否认为有一个默认MAP类型,如果您愿意,您可以使用更具体的类型?
    • Dilbert 是不带引号的字符串文字吗?

最后,我会向您指出另一个配置 DSL,尽管可能更多用于系统管理员:Puppet

走好。

于 2008-12-22T00:55:58.677 回答
0

我将提供一些关于 Spring 的背景知识以及它的 applicationContext.xml 文件——这将使 SFig 语法中发生的一些事情变得清晰。

applicationContext.xml 文件用于表示将由 Spring bean 工厂管理的 bean 的 bean 初始化。因此,鉴于我在此文件的 SFig 版本中看到的 bean 示例,在 Java 应用程序代码中,可能会请求 bean 工厂创建一个 bean 实例,如下所示:

SqlMapClient sqlMapClient = getBean("sqlMapClient");

bean 工厂负责 bean 所需的任何实例化和初始化 - 甚至到注入依赖项的程度。在这种情况下,SqlMapClient bean 需要一个dataSource bean 的实例(在 SFig 示例中也对其进行了描述和引用)。

bean 描述符将以下信息传递给 bean 工厂:

  • bean 的 Java 类名
  • 请求或引用它的 bean ID
  • bean 定义元属性(可选)
  • 构造函数初始化参数(可选)
  • 和/或属性初始化器

'@' 前缀 bean 定义元属性。这些是 bean 工厂用来管理 bean 的属性。例如,@scope = singleton,将通知 bean 工厂创建 bean 的单个实例,缓存它,并在请求时分发对它的引用。可以设置的和 Spring-Framework 定义的一样。

如果要通过构造函数初始化 bean,那么在 SFig 中,它通过一种语法表示,该语法似乎是用括号中的参数调用this 。

或者可以通过设置其属性来初始化 bean。分配给但不以“@”为前缀的标识符是 bean 属性。

当引用作为必需依赖项的 bean 时,可以通过在其 bean ID 前加上“$”来引用它。这方面的几个例子出现在 SFig 例子中。

出现在字符串文字中的 ${foo.bar} 样式的变量将被 Java 属性值替换。在这种情况下,属性是通过以下行从文件 application.properties 加载的:

properties_include "classpath:application.properties";

如果在任何包含的属性中都找不到 Java System 属性,则将查找下一个。这是许多 Java 框架中广泛遵循的做法。当前基于 XML 的 applicationContext.xml 文件也有一种允许这种用法的方式。

因为 java.util.Properties 经常用于初始化 bean,所以 SFig 提供了 PROPERTIES 作为一种特殊的方便语法来声明一个 Properties 对象。java.util.List 也是如此,它具有相应的 SFig LIST。此外,值数组可以在方括号 [...] 中声明。

此外,还有用于声明多行文本块的 TEXT。以字符串文字为前缀的“@”表示关闭转义编码——一种从 C# 借用的语言语法。

SFig DSL 的主要设计目标之一是在本质上保持声明性。我故意避免添加任何命令式脚本功能。嵌入在文本配置文件中的编程逻辑的复杂性意味着必须对其进行调试。不想打开代码调试的另一个维度。

于 2008-12-22T04:18:37.740 回答