在grails应用程序中从定制groovy文件加载spring bean [英] Load spring beans from custom groovy files in grails app
问题描述
2.3.7中的定制groovy文件加载spring bean。我知道这个问题以前已经问过,但经过几个小时的搜索,我无法以找到从classpath加载的一致方法。
目标
- 将
resources.groovy
模块化为多个自定义资源文件
- 将自定义资源文件放在标准位置:
grails-app / conf / spring
- 使用插件来实现魔法;尽量减少开销
试过...
beans {
testsvc(TestService){
msg ='hello'
}
}
注意上面,我使用 beans {}
,而不是 beans = {}
,显然是它有所作为:
resources.groovy
这样做...
beans = {
loadBeans'file:C:\\Proj\Test1\grails-app\\\\\\\\spring\\MyBeansConfig.groovy'
}
...并根据 docs ,这也应该是,但不会:
importBeans(classpath:* MyBeansConfig.groovy)
更新 - 工作选项
(适用于Grails 2.3.7)
选项1:(src / java)
按照 lukelazarovic a>建议,因为Grails会自动将 自定义bean配置文件在 插件配置 Grails应用程序 没有配置! bean配置文件使用 发现选项存在一些问题3: 我们设法解决了上述问题,在eclipse,WAR,test-app等中执行Grails时,它们的工作方式是一样的。 在grails-app / conf / spring 第一步:我们创建了一个类,以更好地控制定位和加载资源文件;这是必要的,因为一些文件由于交叉引用的bean而被加载了多次。 已删除 src / java
中的groovy文件复制到类路径中,在eclipse和战争部署中工作正常:
pre code $ // config配置文件
src / java / MyBeansConfig.groovy
src / java / FooBeansConfig.groovy
//resources.groovy
loadBeans('classpath *:* BeansConfig.groovy')
选项2:(grails-app / conf / spring)
grails-app / conf / spring
(信用 ideascultor and mark.esher )
//这里的bean配置文件
grails-app / conf / spring / MyBeansConfig.groovy
// ## resources.groovy
//用于eclipse / local测试
loadBeans('file:./ grails-app / conf / spring / * BeansConfig.gro ovy')
//用于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(名称:resources.groovy)
exclude(名称:resources.xml)
}
}
选项3 :(自定义插件)
如果你使用自定义插件,这种方法是理想的;锅炉板配置被重构到插件中:
$ b
// ## scripts / _Events.groovy
eventCreateWarStart = {warName,stagingDir - >
def libDir = new File($ {stagingDir} / WEB-INF / classes / spring)
$ b $ ant.copy(todir:libDir){
fileset(dir: (名称:resources.groovy)
exclude(名称:资源,grails-app / conf / spring){
include(name:* BeansConfig.groovy)
exclude .xml)
}
}
}
// ## MyGrailsPlugin.groovy
def doWithSpring = {
loadBeans('file :./ grails-app / conf / spring / * BeansConfig.groovy')
loadBeans('classpath *:* BeansConfig.groovy')
}
* BeansConfig.groovy
约定,很好!
//这里的bean配置文件
grails-app / conf / spring / MyBeansConfig.groovy
更新9/24/2015
test-app
我们使用一个插件来封装这个功能,所以这个类在这个插件中:
class CustomResourceLoader {
static loadSpringBeans(BeanBuilder bb){
def files = ['*'] //加载所有资源文件
//使用多种方法匹配资源
def matchedResourceList = []
files.each {
matchedResourceList + =
getPatternResolvedResources(file:./ grails-app / conf / spring /+ it +.groovy)。toList()
matchedResourceList + =
getPathMatchedResources(classpath *:spring /+ it +.groovy)。toList()
}
//消除从递归引用加载的重复资源
def resourceMap = [:]
matchedResourceList.each {
if(it)resourceMap.put(it.getFilename(),it)
}
// make resources.groovy第一次进入list
def resourcesFile = resourceMap.remove(resources.groovy)
if(!resourcesFile)
抛出新的RuntimeException(resources.groovy未找到预期的地方!)
def resourcesToLoad = [resourcesFile]
resourceMap.each {k,v - > resourcesToLoad<< v)
log.debug(Spring资源文件即将加载:)
resourcesToLoad.each {bb.loadBeans(it)}
}
static def getPatternResolvedResources(path){
ResourcePatternResolver resourcePatternResolver =
PathMatchingResourcePatternResolver();
返回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)
}
}
}
$ / code>
在插件定义文件中,从 doWithSpring()
,传递 BeanBuilder
(委托)作为参数(非常重要):
def doWithSpring = {
CustomResourceLoader.loadSpringBeans(委托)
}
就是这样,除了在 grails-app / conf / spring
中创建自定义资源文件外, / p>
前几天我有一个类似的问题,用一个groovy配置文件添加到的grails-app / CONF
。虽然这与其他资源(它们在类路径中被复制并可用)一起工作,但groovy文件的问题仅仅是它被编译并且包含类文件,即不是groovy文件本身。
我没有找到任何关于如何完成这个 的好文档,最后只是将它添加到 web-应用程序/ WEB-INF /类
。这里放置的Groovy文件将被复制(不编译)并在类路径中可用。
Trying to load spring beans from custom groovy file in Grails 2.3.7.
I know this question has been asked before, but after hours of searching, I'm unable to find a consistent approach that loads from the classpath.
The Goal
- Modularize
resources.groovy
into multiple custom resource files - Put custom resource files in standard location:
grails-app/conf/spring
- Use plugin to do the magic; minimize overhead
Tried...
//## grails-app/conf/spring/MyBeansConfig.groovy
beans {
testsvc(TestService){
msg = 'hello'
}
}
Note above, I'm using beans {}
, not beans = {}
, apparently it makes a difference:
resources.groovy
This works...
beans = {
loadBeans 'file:C:\\Proj\Test1\grails-app\\conf\\spring\\MyBeansConfig.groovy'
}
...and according to docs, this should too, but doesn't:
importBeans("classpath:*MyBeansConfig.groovy")
UPDATE - WORKING OPTIONS
(working for Grails 2.3.7)
Option 1: (src/java)
Following lukelazarovic advice, this approach works since Grails automatically copies (not compiles) groovy files in src/java
to the classpath; works fine in eclipse and with war deployment:
//bean config files here
src/java/MyBeansConfig.groovy
src/java/FooBeansConfig.groovy
//resources.groovy
loadBeans('classpath*:*BeansConfig.groovy')
Options 2: (grails-app/conf/spring)
This approach allows for custom bean config files in grails-app/conf/spring
(credits to ideascultor and 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")
}
}
}
Options 3: (Custom Plugin)
If you're using custom plugins, this approach is ideal; boiler plate config gets refactored into the plugin:
Plugin Config
//## 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 App
No config!...just create your bean config files using the *BeansConfig.groovy
convention, good to go!
//bean config files here
grails-app/conf/spring/MyBeansConfig.groovy
Update 9/24/2015
Found some issues with option 3:
- loading of duplicate resource files
- spring resources not configured correctly for
test-app
We managed to fix the above issue such that any resource files in grails-app/conf/spring
work the same when executing Grails in eclipse, WAR, test-app, etc.
First step: we created a class to have more control over locating and loading resource files; this was necessary as some files were being loaded more than once due to cross-referenced beans. We're using a plugin to encapsulate this functionality, so this class lives in that plugin:
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)
}
}
Removed BeansConfig.groovy
suffix; WAR generation now picks up any resources in 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")
}
}
}
}
In the plugin definition file, call the loader from doWithSpring()
, passing BeanBuilder
(the delegate) as the argument (very important):
def doWithSpring = {
CustomResourceLoader.loadSpringBeans(delegate)
}
That's it, there is no requirement on users of the plugin aside from creating custom resource files in grails-app/conf/spring
I had a similar problem just a few days ago, with a groovy configuration file that I added into grails-app/conf
. While this works with other resources (they are copied and available on the classpath), the problem with the groovy file was simply that it was compiled and the class file was included, i.e. not the groovy file itself.
I didn't find any good documentation on how this should be done and finally just added it to web-app/WEB-INF/classes
. Groovy files placed here will be copied (not compiled) and available on the classpath.
这篇关于在grails应用程序中从定制groovy文件加载spring bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!