从grails app中的自定义groovy文件加载spring bean

raf*_*ian 8 java grails groovy spring spring-dsl

尝试从Grails中的自定义groovy文件加载spring bean 2.3.7.我之前已经问过这个问题,但是经过几个小时的搜索,我无法找到从类路径加载的一致方法.

目标

  • 模块化resources.groovy为多个自定义资源文件
  • 将自定义资源文件放在标准位置: grails-app/conf/spring
  • 使用插件来做魔术; 最小化开销

试了...

//## grails-app/conf/spring/MyBeansConfig.groovy 
beans {
   testsvc(TestService){
      msg = 'hello'
   }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我正在使用beans {},而不是beans = {},显然它有所不同:

resources.groovy

这有效......

beans = {
  loadBeans 'file:C:\\Proj\Test1\grails-app\\conf\\spring\\MyBeansConfig.groovy'
}
Run Code Online (Sandbox Code Playgroud)

......根据文档,这也应该,但不是:

importBeans("classpath:*MyBeansConfig.groovy")
Run Code Online (Sandbox Code Playgroud)

更新 - 工作选项

(为Grails 2.3.7工作)

选项1:(src/java)

根据lukelazarovic的建议,这种方法有效,因为Grails会自动将groovy文件复制(不编译)src/java到类路径中; 在日食和战争部署中工作正常:

//bean config files here
src/java/MyBeansConfig.groovy
src/java/FooBeansConfig.groovy

//resources.groovy
loadBeans('classpath*:*BeansConfig.groovy')
Run Code Online (Sandbox Code Playgroud)

选项2 :( grails-app/conf/spring)

这种方法允许自定义bean配置文件grails-app/conf/spring(对ideascultormark.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")
         }
      }
   }
Run Code Online (Sandbox Code Playgroud)

选项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') 
   }
Run Code Online (Sandbox Code Playgroud)

Grails App

没有配置!...只是使用*BeansConfig.groovy约定创建你的bean配置文件,很高兴!

//bean config files here
grails-app/conf/spring/MyBeansConfig.groovy
Run Code Online (Sandbox Code Playgroud)

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)
   }
}
Run Code Online (Sandbox Code Playgroud)

删除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")
         }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

在插件定义文件中,从中调用loader doWithSpring(),传递BeanBuilder(委托)作为参数(非常重要):

def doWithSpring = {       
   CustomResourceLoader.loadSpringBeans(delegate)
}
Run Code Online (Sandbox Code Playgroud)

就是这样,除了创建自定义资源文件之外,没有要求插件的用户 grails-app/conf/spring

luk*_*vic 1

我在 Grails 2.1.2 中的自定义 XML 文件也遇到了同样的问题。

AFAIR 在生产环境中使用 XML 资源grails-app/conf/spring是行不通的。

为了使其在开发和生产环境中都能工作,我最终将资源投入到src/java. 我认为您可以通过将 groovy 文件放入src/groovy.