繁体   English   中英

如何在抽象类方法中访问注入的 Grails bean?

[英]How can I access injected Grails beans in an abstract class method?

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

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)
}

我的问题:

当我在 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 上的项目包含以下内容并且似乎有效:

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

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 包演示

class MySpecificBeanImpl implements MyBean {
}

src/groovy/demo/MyBean.groovy

package demo

interface MyBean {}

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

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 包演示

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

您可能会发现那里的某事与您正在做的某事之间存在显着差异。 如果您可以在该示例应用程序中隔离有问题的场景,或者提供可运行的代码版本,那么我很乐意为您解决问题。

我使用@Autowired注释解决了这个问题

import grails.gorm.services.Service
import org.springframework.beans.factory.annotation.Autowired

@Service(User)
abstract class UserService {

    @Autowired
    OrganizationService organizationService

    //...
}

在 Grails 3.3.5 上测试

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM