从 grails 应用程序中的自定义 groovy 文件加载 spring bean
Posted
技术标签:
【中文标题】从 grails 应用程序中的自定义 groovy 文件加载 spring bean【英文标题】:Load spring beans from custom groovy files in grails app 【发布时间】:2014-07-24 13:41:39 【问题描述】:尝试从 Grails 2.3.7.
中的自定义 groovy 文件加载 spring bean 我知道这个问题之前已经被问过,但经过数小时的搜索,我无法找到从类路径加载的一致方法。
目标
将resources.groovy
模块化成多个自定义资源文件
将自定义资源文件放在标准位置:grails-app/conf/spring
使用插件来变魔术;尽量减少开销
试过...
//## grails-app/conf/spring/MyBeansConfig.groovy
beans
testsvc(TestService)
msg = 'hello'
请注意,我使用的是beans
,而不是beans =
,apparently,这会有所不同:
resources.groovy
这行得通...
beans =
loadBeans 'file:C:\\Proj\Test1\grails-app\\conf\\spring\\MyBeansConfig.groovy'
...根据docs,这也应该,但不是:
importBeans("classpath:*MyBeansConfig.groovy")
更新 - 工作选项
(适用于 Grails 2.3.7)
选项一:(src/java)
遵循lukelazarovic 的建议,这种方法有效,因为Grails 自动将src/java
中的groovy 文件复制(而不是编译)到类路径;在 Eclipse 和战争部署中工作正常:
//bean config files here
src/java/MyBeansConfig.groovy
src/java/FooBeansConfig.groovy
//resources.groovy
loadBeans('classpath*:*BeansConfig.groovy')
选项 2:(grails-app/conf/spring)
这种方法允许在 grails-app/conf/spring
中自定义 bean 配置文件(感谢 ideascultor 和 mark.esher)
//bean config files here
grails-app/conf/spring/MyBeansConfig.groovy
//## resources.groovy
//for eclipse/local testing
loadBeans('file:./grails-app/conf/spring/*BeansConfig.groovy')
//for WAR/classpath
loadBeans('classpath*:*BeansConfig.groovy')
//## BuildConfig.groovy
grails.war.resources = stagingDir, args ->
copy(todir: "$stagingDir/WEB-INF/classes/spring")
fileset(dir:"grails-app/conf/spring")
include(name: "*BeansConfig.groovy")
exclude(name: "resources.groovy")
exclude(name: "resources.xml")
选项 3:(自定义插件)
如果您使用自定义插件,这种方法是理想的;样板配置被重构到插件中:
插件配置
//## scripts/_Events.groovy
eventCreateWarStart = warName, stagingDir ->
def libDir = new File("$stagingDir/WEB-INF/classes/spring")
ant.copy(todir: libDir)
fileset(dir:"grails-app/conf/spring")
include(name: "*BeansConfig.groovy")
exclude(name: "resources.groovy")
exclude(name: "resources.xml")
//## MyGrailsPlugin.groovy
def doWithSpring =
loadBeans('file:./grails-app/conf/spring/*BeansConfig.groovy')
loadBeans('classpath*:*BeansConfig.groovy')
Grails 应用程序
没有配置!...只需使用*BeansConfig.groovy
约定创建您的 bean 配置文件,一切顺利!
//bean config files here
grails-app/conf/spring/MyBeansConfig.groovy
2015 年 9 月 24 日更新
发现选项 3 存在一些问题:
加载重复的资源文件 没有为test-app
正确配置spring资源
我们设法解决了上述问题,使得grails-app/conf/spring
中的任何资源文件在 eclipse、WAR、test-app 等中执行 Grails 时都可以正常工作。
第一步:我们创建了一个类来更好地控制资源文件的定位和加载;这是必要的,因为由于交叉引用的 bean,一些文件被多次加载。 我们使用一个插件来封装这个功能,所以这个类存在于那个插件中:
class CustomResourceLoader
static loadSpringBeans(BeanBuilder bb)
def files = ['*'] //load all resource files
//match resources using multiple methods
def matchedResourceList = []
files.each
matchedResourceList +=
getPatternResolvedResources("file:./grails-app/conf/spring/" + it + ".groovy").toList()
matchedResourceList +=
getPathMatchedResources("classpath*:spring/" + it + ".groovy").toList()
//eliminate duplicates resource loaded from recursive reference
def resourceMap = [:]
matchedResourceList.each
if(it) resourceMap.put(it.getFilename(), it)
//make resources.groovy first in list
def resourcesFile = resourceMap.remove("resources.groovy")
if(!resourcesFile)
throw new RuntimeException("resources.groovy was not found where expected!")
def resourcesToLoad = [resourcesFile]
resourceMap.eachk,v -> resourcesToLoad << v
log.debug("Spring resource files about to load: ")
resourcesToLoad.each bb.loadBeans(it)
static def getPatternResolvedResources(path)
ResourcePatternResolver resourcePatternResolver =
new PathMatchingResourcePatternResolver();
return resourcePatternResolver.getResources(path);
static def getPathMatchedResources(path)
return new PathMatchingResourcePatternResolver().getResources(path)
去掉BeansConfig.groovy
后缀; WAR 生成现在可以获取 grails-app/conf/spring
中的任何资源
plugin, _Events.groovy
eventCreateWarStart = warName, stagingDir ->
def libDir = new File("$stagingDir/WEB-INF/classes/spring")
ant.copy(todir: libDir)
fileset(dir:"grails-app/conf/spring")
include(name: "*.groovy")
exclude(name: "resources.xml")
在插件定义文件中,从doWithSpring()
调用加载器,传递BeanBuilder
(委托)作为参数(非常重要):
def doWithSpring =
CustomResourceLoader.loadSpringBeans(delegate)
就是这样,除了在grails-app/conf/spring
创建自定义资源文件外,对插件用户没有任何要求
【问题讨论】:
感谢您整理以上所有信息!谢谢! @mowwwalker 感谢您提醒我更新这篇文章!请参阅上面的更改,希望对您有所帮助! 【参考方案1】:几天前我遇到了类似的问题,我在grails-app/conf
中添加了一个 groovy 配置文件。虽然这适用于其他资源(它们被复制并在类路径上可用),但 groovy 文件的问题只是它被编译并包含了类文件,即不是 groovy 文件本身。
我没有找到任何关于如何应该完成的好的文档,最后只是将它添加到web-app/WEB-INF/classes
。放置在此处的 Groovy 文件将被复制(未编译)并在类路径中可用。
【讨论】:
【参考方案2】:我在 Grails 2.1.2 中使用自定义 XML 文件时遇到了同样的问题。
在grails-app/conf/spring
中拥有 XML 资源在生产环境 AFAIR 中不起作用。
为了使其在开发和生产环境中都能正常工作,我最终将资源放入 src/java
。我认为您可以通过将 groovy 文件放入 src/groovy
来获得相同的结果。
【讨论】:
src/java 应该可以工作,但是我相信 src/groovy 会编译这个类,我记得昨晚读过一些关于那个的东西,你可以确认吗? 我不知道你是什么意思 - 当你运行 grails war 时,所有的 groovy 文件,包括 grails-app 中的文件都会编译成类文件 我知道,但是loadBeans()
读取 groovy 文件,它不适用于类文件;当配置文件驻留在 src/groovy 中时,它似乎不起作用(刚刚测试过)【参考方案3】:
我们也可以通过以下方式从不同的 groovy/xml 文件中导入 bean:- 在 resources.groovy 中使用以下内容 -
importBeans 'file:camel-beans.groovy' 要么 importBeans('classpath:/camel-config.xml')
将 camel-beans.groovy 与 resources.groovy 一起放置,并为第一种情况提供包作为“包 spring”,否则将其放在 web 应用程序类路径中并使用第二种方式。
【讨论】:
【参考方案4】:如果您的 resources.groovy 位于以下路径
grails-app/conf/spring/resources.groovy
而您的 camel-beans.groovy 位于以下路径
grails-app/conf/spring/camel-beans.groovy
然后您可以通过在 resources.groovy 中添加以下行来引用 resources.groovy 文件中的 camel-beans.groovy
importBeans('file:**/camel-beans.groovy')
【讨论】:
以上是关于从 grails 应用程序中的自定义 groovy 文件加载 spring bean的主要内容,如果未能解决你的问题,请参考以下文章
Grails 2.2.1 无法识别从 BuildConfig.groovy 安装的“发布”插件
Grails / Groovy / GGTS:运行应用程序上的模块版本冲突