我如何在抽象类方法中访问注入的Grails bean? [英] How can I access injected Grails beans in an abstract class method?

查看:144
本文介绍了我如何在抽象类方法中访问注入的Grails bean?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个抽象类,它实现了大量被注册为bean的具体类继承的许多功能。这些bean是通过自动装配定义的。例如:

 抽象类MyAbstract {

MyService myService
MyBean myBean

def doSomething(){
def value = myService.something(myBean)
}
}


MyConcrete扩展MyAbstract {
def concreteField
$ b $ def def doSomethingElse(){
def value = myService.somethingElse(myBean)
}
}


$ b

conf / spring / resources.groovy:

  myConcrete(MyConcrete){bean  - > 
bean.autowire = true
myBean = ref(MySpecificBeanImpl)
}

我的问题:

当我在MyConcrete实例中运行方法doSomethingElse时,一切都按预期工作,myService和myBean值用适当的值填充DI。当我在MyConcrete实例中执行doSomething方法时,myService和myBean值都为空。看起来DI值在子类继承的抽象方法中不可见。这真的很糟糕。

我可以使用方法中的上下文持有者手动访问值,或者我可以使用修改后的方法将值从子类传递给抽象父类接受这些值作为参数的签名,但这些都不是好的解决方案。它彻底打破了抽象类实现的实用性,并且需要大量我不想维护的复制代码。

更糟的是,在我的具体情况中, myBean的值实际上不同于每个具体类,显式连接在resources.groovy文件中,所以通用持有者方法无效。



我看过通过一些与此相关的职位,包括抽象类中的Grails服务,没有太多结果弄清楚发生了什么事。抽象bean定义似乎是关于抽象bean定义属性,并且与抽象类和子类继承没有任何关系。

(1)这是Grails / Spring DI支持的限制吗?
(2)对于抽象类,我还需要做些什么吗?

解决方案

您已经遗漏了一些细节,我不得不做出一些假设,但我创建了一个类似于你正在描述。 https://github.com/jeffbrown/abstractbeanmethods 中的项目包含以下内容,似乎可以正常工作:



/ groovy / demo / MyAbstract.groovy
包演示

 <$ c $ my $ b $ MyEbstract {

MyService myService
MyBean myBean
$ b $ def doSomething(){
myService.something(myBean)
}
}



/ groovy / demo / MyConcrete.groovy

 包演示

类MyConcrete扩展MyAbstract {
def doSomethingElse(){
def value = myService .somethingElse(myBean)
}
}

grails-app / conf / spring / resources.groovy

  //将您的Spring DSL代码放在这里
beans = {
myBeanImpl demo .MySpecificBeanImpl

myConcrete(demo.MyConcrete){bean - >
bean.autowire = true
myBean = ref('myBeanImpl')
}
}



src / groovy / demo / MySpecificBeanImpl.groovy
包演示

  class MySpecificBeanImpl实现MyBean {
}



/ src / groovy / demo / MyBean.groovy

 包演示

接口MyBean {}

grails-app / service / demo / MyService.groovy
包演示
$ b

  class MyService {

在MyService.something()方法中定义了一些Bean类名称$ {bean.class.name} $ b $
$ b def somethingElse(MyBean bean){
MyService.somethingElse()方法中的Bean类名是$ {bean.class.name}
$ b $

grails-app / controllers / demo / DemoController.groovy
套餐演示

  class DemoController {
def myConcrete
def index(){
def sb = new StringBuffer()
sb<< myConcrete.doSomething()
sb<< 和
sb<< myConcrete.doSomethingElse()
render sb
}
}

你可能会发现一些东西和你正在做的事情之间的一些重大差异。如果您可以在该示例应用程序中隔离出现问题的场景,或者提供可运行版本的代码,那么我会很乐意为您解决它。


I have an abstract class that implements much of the functionality inherited by a large number of concrete classes that are registered as beans. The beans are defined with autowiring on. For example:

abstract class MyAbstract {

    MyService myService
    MyBean myBean

    def doSomething() {
        def value = myService.something(myBean)
    }
}


class MyConcrete extends MyAbstract {
    def concreteField

    def doSomethingElse() {
         def value = myService.somethingElse(myBean)
    }
}

conf/spring/resources.groovy:

myConcrete(MyConcrete) { bean ->
    bean.autowire = true
    myBean = ref(MySpecificBeanImpl)
}

My Problem:

When I run the method doSomethingElse in a MyConcrete instance, everything works as expected and the myService and myBean values are filled in with the proper values by DI. When I execute the doSomething method in a MyConcrete instance, both the myService and myBean values are null. It appears that the DI values are not visible in the abstract method inherited by the subclass. That really sucks.

I can manually access the values using a context holder in the method or I can pass the values from the subclass to the abstract parent class using a modified method signature that accepts those values as parameters, but these are no good solutions. It completely breaks the usefulness of abstract class implementations and requires a lot of replicated code that I don't want to have to maintain.

Even worse, in my specific case, the value of myBean is actually different for each concrete class, explicitly wired in the resources.groovy file, so the generic holder approach doesn't work.

I've looked through a number of posts relating to this including Grails services in abstract class without much result in figuring out what is going on. The abstract bean definition seems to be about abstracting the bean definition properties and doesn't have anything to do with abstract classes and subclass inheritance.

(1) Is this a limitation in the Grails/Spring DI support? (2) Is there something else I need to do wrt the abstract class?

解决方案

You have left out some details and I have had to make some assumptions but I have created an app with something similar to what you are describing. The project at https://github.com/jeffbrown/abstractbeanmethods contains the following and appears to work:

src/groovy/demo/MyAbstract.groovy package demo

abstract class MyAbstract {

    MyService myService
    MyBean myBean

    def doSomething() {
        myService.something(myBean)
    }
}

src/groovy/demo/MyConcrete.groovy

package demo

class MyConcrete extends MyAbstract {
    def doSomethingElse() {
         def value = myService.somethingElse(myBean)
    }
}

grails-app/conf/spring/resources.groovy

// Place your Spring DSL code here
beans = {
    myBeanImpl demo.MySpecificBeanImpl

    myConcrete(demo.MyConcrete) { bean ->
        bean.autowire = true
        myBean = ref('myBeanImpl')
    }
}

src/groovy/demo/MySpecificBeanImpl.groovy package demo

class MySpecificBeanImpl implements MyBean {
}

src/groovy/demo/MyBean.groovy

package demo

interface MyBean {}

grails-app/service/demo/MyService.groovy package demo

class MyService {

    def something(MyBean bean) {
        "Bean class name is ${bean.class.name} in MyService.something() method"
    }
    def somethingElse(MyBean bean) {
        "Bean class name is ${bean.class.name} in MyService.somethingElse() method"
    }
}

grails-app/controllers/demo/DemoController.groovy package demo

class DemoController {
    def myConcrete
    def index() {
        def sb = new StringBuffer()
        sb << myConcrete.doSomething()
        sb << " and "
        sb << myConcrete.doSomethingElse()
        render sb
    }
}

You may find some significant difference between something there and someting that you are doing. If you can isolate a problematic scenario in that sample app, or provide a runnable version of your code then I will be happy to straighten it out for you.

这篇关于我如何在抽象类方法中访问注入的Grails bean?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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