Grails Dependency Injection Outside of Services?

血红的双手。 提交于 2019-12-10 13:23:07

问题


I have a Grails application that needs to run a strategy that will likely be swapped out over time. I know Spring underlies Grails, so I was wondering if I had access to Spring's IoC container so that I could externalize the actual dependency in an xml file (note: I have never actually done this, but just know of it, so I may be missing something). My goal is to be able to do something like the following:

class SchemaUpdateService {
public int calculateSomething(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
IStrategy strat = (IStrategy) ctx.getBean("mystrat");
}
}

And then map the appropriate implementation in the beans.xml file. I assume this is supported in Grails. Does anyone have any documentation on how this would work? Do I really just need the Spring IoC library and it will just work? Thanks!


回答1:


You define your beans in resources.xml or resources.groovy. The grails documentation is very clear about how to access the Spring application context.




回答2:


You can access the application context from any Grails artefact using

ApplicationContext ctx = grailsApplication.mainContext

You can then use this to retrieve whichever beans you're interested in:

IStrategy strat = (IStrategy) ctx.getBean("mystrat")

In classes that don't have access to grailsApplication, you could use a helper such as the following to access the application context and the beans therein

class SpringUtils {

    static getBean(String name) {
        applicationContext.getBean(name)
    }

    static <T> T getBean(String name, Class<T> requiredType) {
        applicationContext.getBean(name, requiredType)
    }

    static ApplicationContext getApplicationContext() {
        ApplicationHolder.application.mainContext
    }
}

However, this should only be necessary if you need to retrieve different implementations of the same bean at runtime. If the required bean is known at compile-time, just wire the beans together in resources.xml or resources.groovy




回答3:


First of all, you want to define your strategy in your grails-app/conf/spring/resources.groovy:

beans = {
    myStrat(com.yourcompany.StrategyImpl) {
       someProperty = someValue
    }
}

Then, you simply def the a property with the same name into your service:

class SomeGrailsService {
    def myStrat

    def someMethod() {
        return myStrat.doSomething()
    }
}

In any Grails artefact (such as services and domain classes), Grails will automatically give the myStrat property the correct value. But don't forget, in a unit test you'll have to give it a value manually as the auto-wiring does not happen in unit tests.

Outside of a Grails artefact, you can use something like:

def myStrat = ApplicationHolder.application.mainContext.myStrat

In Grails 2.0, Graeme et al are deprecating the use of the *Holder classes (such as ApplicationHolder and ConfigurationHolder), so I'm not quite sure what the Grails 2.0 approach would be...



来源:https://stackoverflow.com/questions/7350266/grails-dependency-injection-outside-of-services

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!