尝试从 Grails 中的自定义 groovy 文件加载 spring bean2.3.7.
我知道这个问题之前已经被问过,但是经过数小时的搜索,我无法找到从类路径加载的一致方法。
目标
- 模块化
resources.groovy
成多个自定义资源文件 - 将自定义资源文件放在标准位置:
grails-app/conf/spring
- 使用插件来做魔术;最小化开销
试过...
//## grails-app/conf/spring/MyBeansConfig.groovy
beans {
testsvc(TestService){
msg = 'hello'
}
}
请注意上面,我使用的是beans {}
,而不是beans = {}
,显然它有所不同:
资源.groovy
这有效...
beans = {
loadBeans 'file:C:\\Proj\Test1\grails-app\\conf\\spring\\MyBeansConfig.groovy'
}
...并且根据docs,这也应该,但不是:
importBeans("classpath:*MyBeansConfig.groovy")
更新 - 工作选项
(为 Grails 2.3.7 工作)
选项 1: (src/java)
遵循lukelazarovic 的建议,这种方法很有效,因为 Grails 会自动将 groovy 文件复制(而不是编译)src/java
到类路径中;在 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
( ideascultor和mark.esher的学分)中使用自定义 bean 配置文件
//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 应用程序
没有配置!...只需使用约定创建您的 bean 配置文件*BeansConfig.groovy
,一切顺利!
//bean config files here
grails-app/conf/spring/MyBeansConfig.groovy
2015 年 9 月 24 日更新
发现选项 3 的一些问题:
- 加载重复的资源文件
- 弹簧资源未正确配置
test-app
我们设法解决了上述问题,以便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.each{k,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