在grails应用程序中从定制groovy文件加载spring bean [英] Load spring beans from custom groovy files in grails app

查看:109
本文介绍了在grails应用程序中从定制groovy文件加载spring bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试从Grails 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会自动将 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)



自定义bean配置文件在 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')
}

Grails应用程序

没有配置! bean配置文件使用 * BeansConfig.groovy 约定,很好!

  //这里的bean配置文件
grails-app / conf / spring / MyBeansConfig.groovy



更新9/24/2015



发现选项存在一些问题3:


  • 加载重复资源文件
  • 弹簧资源未正确配置为 test-app



我们设法解决了上述问题,在eclipse,WAR,test-app等中执行Grails时,它们的工作方式是一样的。



在grails-app / conf / spring 第一步:我们创建了一个类,以更好地控制定位和加载资源文件;这是必要的,因为一些文件由于交叉引用的bean而被加载了多次。
我们使用一个插件来封装这个功能,所以这个类在这个插件中:

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆