SFig 语言语法是否高效且清晰(并且比 Spring-Framework 的 XML DSL 更好)?
附录编辑:
尚未接受对此的回答,因为 还没有任何反馈 经验丰富的Spring框架 开发人员。
我一直在研究用于 Spring-Framework applicationContext.xml 文件的替代 DSL(其中描述了 bean 初始化和依赖关系,以便加载到 Spring bean 工厂中)。
我的动机是,我完全不喜欢 Spring 为此目的使用 XML,也不喜欢迄今为止设计的任何替代方案。 由于各种原因(我不会详述),我想继续使用声明性语言,而不是像 Groovy 这样的命令式脚本语言。
因此,我使用了 ANTLR 解析器工具,并设计了一种新的 bean 工厂 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"]];
}
ADDENDUM EDIT:
Have not accepted an answer to this as
there has not been any feedback from
experienced Spring Framework
developers.
I've been working on a replacement DSL to use for Spring-Framework applicationContext.xml files (where bean initialization and dependency relationships are described for loading up into the Spring bean factory).
My motivation is that I just flat out don't like Spring's use of XML for this purpose nor do I really like any of the alternatives that have been devised so far. For various reasons that I won't go into, I want to stay with a declarative language and not some imperative scripting language such as Groovy.
So I grabbed the ANTLR parser tool and have been devising a new bean factory DSL that I've dubbed SFig. Here's a link that talks more about that:
SFig™ - alternative metadata config language for Spring-Framework
And here is the source code repository site:
http://code.google.com/p/sfig/
I'm interested to know how I'm doing on the language syntax so far. Do you think SFig is both efficient and clear to understand? (I'm particularly concerned right now with the mulit-line text string):
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"]];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我将提供一些有关 Spring 及其 applicationContext.xml 文件的背景知识 - 这将使 SFig 语法中发生的一些事情变得清晰。
applicationContext.xml 文件用于表示将由 Spring bean 工厂管理的 bean 的 bean 初始化。 因此,给出在该文件的 SFig 版本中看到的 bean 示例,在 Java 应用程序代码中,人们可能会请求 bean 工厂创建一个 bean 实例,如下所示:
bean 工厂负责 bean 所需的任何实例化和初始化 -甚至到注入依赖项的程度。 在这种情况下,SqlMapClient bean 需要一个 dataSource bean 的实例(在 SFig 示例中也对此进行了描述和引用)。
bean 描述符将以下信息转发给 bean 工厂:
项 “@”前缀bean 定义元属性。 这些是 bean 工厂用来管理 bean 的属性。 例如,@scope = singleton,将通知 bean 工厂创建该 bean 的单个实例,对其进行缓存,并在请求时分发对其的引用。 可以设置的内容与 Spring-Framework 定义的相同。
如果要通过构造函数初始化一个 bean,那么在 SFig 中,它的表达方式似乎是使用括号中的参数调用 this。
或者可以通过设置 bean 的属性来初始化 bean。 分配给但不以“@”为前缀的标识符是 bean 属性。
当引用一个必需依赖项的 bean 时,可以通过在其 bean ID 前加上“$”前缀来引用它。 SFig 示例中出现了几个这样的示例。
字符串中出现的变量 ${foo.bar} 样式将被 Java 属性值替换。 在这种情况下,属性通过以下行从文件 application.properties 加载:
如果在任何包含的属性中找不到,则将查找下一个 Java 系统属性。 这是许多 Java 框架中广泛遵循的做法。 当前基于 XML 的 applicationContext.xml 文件也有一种允许这种使用的方法。
由于 java.util.Properties 通常用于初始化 beans,因此 SFig 提供了 PROPERTIES 作为声明 Properties 对象的特殊方便语法。 对于 java.util.List 也是如此,它具有相应的 SFig LIST。 此外,值数组可以在方括号 [...] 内声明。
此外,还有用于声明多行文本块的 TEXT。 字符串文字前面的“@”意味着关闭转义编码——一种从 C# 借用的语言语法。
SFig DSL 的主要设计目标之一是保持声明性。 我故意不添加任何命令式脚本功能。 文本配置文件中嵌入的编程逻辑的复杂性意味着必须对其进行调试的可能性。 不想打开代码调试的另一个维度。
I'll provide a bit of background on Spring and it's applicationContext.xml file - that will lend clarity to some of the things going on in SFig syntax.
The applicationContext.xml file is used to express bean initialization for beans that will be managed by the Spring bean factory. So given the example of beans seen in my SFig version of this file, in Java application code one might request the bean factory to make an instance of a bean like so:
The bean factory takes care of any instantiation and initialization that the bean requires - even to the point of injecting dependencies. In this case, a SqlMapClient bean needs an instance of a dataSource bean (which is also described and referenced in the SFig example).
A bean descriptor relays the following information to the bean factory:
The '@' prefixes bean definition meta attributes. These are attributes that are used by the bean factory to manage the bean. For instance, @scope = singleton, would inform the bean factory to make a single instance of the bean, cache it, and hand out references to it when it is requested. The ones that can be set are the same ones defined by the Spring-Framework.
If a bean is to be initialized via a constructor, then that is expressed in SFig by a syntax that appears to be invoking this with arguments in parenthesis.
Or a bean can be initialized by setting its properties. Identifiers that are assigned to and not prefixed by '@' are bean properties.
When referencing a bean that is a required dependency, then it can be referred to by prefixing it's bean ID with '$'. Several examples of this appear in the SFig example.
The ${foo.bar} syle of variable appearing in string literals will be replaced by a Java property value. In this case, properties are loaded from the file application.properties via this line:
Java System properties will be looked to next if not found in any included properties. This is a widely followed practices in many Java frameworks. The current XML-based applicationContext.xml file has a way of permitting this usage too.
Because java.util.Properties are often used to initialize beans, SFig provides the PROPERTIES as a special convenient syntax for declaring a Properties object. Likewise for java.util.List, which has the corresponding SFig LIST. Also, arrays of values can be declared within square brackets [...].
Additionally there is TEXT for declaring blocks of multi-line text. The '@' prefixing a string literal means to turn off escape encoding - a language syntax borrowed from C#.
One of the primary design objectives of the SFig DSL is to remain declarative in nature. I purposely am refraining from adding any imperative scripting features. The complexity of programming logic embedded in a text configuration file will imply possibility of having to debug it. Don't want to open yet another dimension of code debugging.
我对您引用的 Spring XML 没有太多经验,因此您应该对以下反馈持保留态度。
第二个和第三个警告:
一个更大的元问题:作为 DSL,您是否尝试对 Spring 进行配置,还是作为更通用的框架类?
那里:买者自负。 现在是我主观且不完整的反馈;)
我不确定我是否理解为什么您的
scope
具有@
前缀 和destroy-method
,但不是driverClassName
。 此外,xml 大小写和驼峰命名法的混合一开始并不完全明显。@
前缀是类型修饰符,还是语言中的这些关键字?我不完全确定您对块头格式的意图。 你有类名,然后是该类的函数; 目的是指定您将用于特定功能的类吗?
例如
甚至:
我喜欢变量替换; 我认为这些值将来自系统属性?
我喜欢能够指定字符串文字(无需转义),特别是对于您所显示的正则表达式。 然而,拥有多字符引用或引用修饰符似乎有点陌生。 我猜你考虑过单引号(shell 和 Perl 对文字字符串使用单引号)。
另一方面,我认为多行
TEXT
的三重正斜杠是正确的方法,但两个让人想起C风格语言中的注释。 Python 使用三重"
来达到此目的。一些 shell 习语具有我不会复制的多行文本约定。我非常喜欢属性和配置位置的外观,使用看起来像 URI 寻址概念的东西。 如果这是一个 URI,
classpath://file.xml
可能会更清晰。 不过,我可能搞错了。我也非常喜欢你所拥有的列表和地图文字的概念,尽管我不确定在哪里:
this
进入其中(我猜是对 Java 构造函数的调用)MAP
类型,如果您愿意,您可以使用更具体的类型?最后,我会向您指出另一个配置 DSL,尽管可能更适合系统管理员使用:Puppet。
走好。
I haven't much experience with the Spring XML you refer, so you should take the following feedback with a pinch of salt.
As a second and third caveat:
A larger, meta-, question: as a DSL are you trying to do configuration of Spring, or as a more general class of frameworks?
There: caveat emptor. Now my subjective and incomplete feedback ;)
I'm not sure I understand the reason why you have the
@
prefix forscope
anddestroy-method
, but notdriverClassName
. Also the mix of both xml-case and camelCase isn't completely apparent to start with. Is the@
prefix a type modifier, or are these keywords in the language?I'm not completely sure of your intentions about the block header format. You have class name, then a function of that class; is the intention to specify what class your are going to use for a particular function?
e.g.
or even:
I like the variable substitution; I presume the values will come from System properties?
I like being able to specify string literals (without escaping), especially for the regular expressions you've shown. However, having multi-character quote or quote modifier seems a little alien. I guess you considered the single-quote (shell and Perl use single-quotes for literal strings).
On the other hand, I think the triple forward slash for multi-line
TEXT
is the right approach, but two reminiscent of comments in C-style languages. Python uses a triple"
for this purpose. Some shell idioms have a multi-line text convention I would not copy.I very much like the look of properties and config location, using what looks like a URI notion of addressing. If this is a URI,
classpath://file.xml
may be clearer. I may have the wrong end of the stick here, however.I also very much like the notion of list and map literals you have, though I'm not sure where:
this
comes into it (I guess a call to a Java constructor)MAP
type, which you can be more specific type if you wish to?Finally, I'd point you to another configuration DSL, though perhaps more for sysadmin usage: Puppet.
Go well.