将从共享接口继承的多个Spring bean注入服务中的数组

时间:2012-02-29 01:06:55

标签: spring grails dependency-injection

我遇到了一个我在另一个项目中遇到的情况,我不确定Grails中最好的方法。要设置它,这就是我在一个普通的Spring项目中所做的。

我有两个继承自同一界面的类:

public interface BaseInterface {
    void doSomething();
}

public class Impl1 implements BaseInterface {
    public void doSomething(){
        System.out.println("doing impl 1");
    }
}

public class Impl2 implements BaseInterface {
    public void doSomething(){
        System.out.println("doing impl 2");
    }
}

到目前为止,相当标准,我有N豆,我想按顺序调用它来做工作。 (这个例子显然是微不足道的)。在另一个Java类中,我可以做一些魔术来将所有bean注入(autowired)作为数组。

@Autowired(required=false)
    private BaseInterface[] theWorkers;

只要我在配置中将它们添加到bean容器中,这将为我提供一系列工作bean。

现在我正在尝试在Grails中做同样的事情。相同的公式不起作用。将@Autowired部分放入服务中,并在resources.groovy中创建Impl1和Impl2似乎不起作用。所以我想知道最好的解决方案是什么:

1)我遗漏了一些简单易用的东西。

2)做一些类似于duffymo here建议的事情。我在resources.groovy中创建了一个使用自定义工厂的命名bean。该工厂将发出一个包含实现某个接口的所有类的类。我会使用类似于建议的东西来提取符合条件的服务/类,然后让该服务允许某人迭代它的子类来完成工作。

3)为resources.groovy中的每个Impl#类创建一个命名bean,然后只使用它们的不同名称并将它们全部注入到各个类中。这个选项不会真正扩展或给予太大的动力,但可行。

1 个答案:

答案 0 :(得分:6)

如果您可以访问Spring应用程序上下文,则可以调用getBeansOfType,它返回实现指定接口或扩展指定基类的所有已知bean。所以我在resources.groovy中注册每个bean,但也是一个管理器类,它获取对应用程序上下文的引用,并为您找到接口实现。你说你想按顺序调用它们,所以你也应该实现Ordered接口。

这是经理类(将它放在src / groovy /包中的正确文件夹中,并将其重命名为您想要的任何内容):

package com.foo

import org.springframework.beans.factory.InitializingBean
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware

class BaseInterfaceManager implements ApplicationContextAware, InitializingBean {

   ApplicationContext applicationContext

   List<BaseInterface> orderedImpls

   void afterPropertiesSet() {
      orderedImpls = applicationContext.getBeansOfType(BaseInterface).values().sort { it.order }
   }
}

然后更改bean,以便它们实现Ordered

import org.springframework.core.Ordered;

public class Impl1 implements BaseInterface, Ordered {
   public void doSomething(){
      System.out.println("doing impl 1");
   }

   public int getOrder() {
      return 42;
   }
}

import org.springframework.core.Ordered;

public class Impl2 implements BaseInterface, Ordered {
   public void doSomething(){
      System.out.println("doing impl 2");
   }

   public int getOrder() {
      return 666;
   }
}

resources.groovy中注册所有三个(使用你想要的任何bean名称):

beans = {

   impl1(Impl1)
   impl2(Impl2)

   baseInterfaceManager(BaseInterfaceManager)
}

然后你可以在服务或控制器中添加依赖注入,或者为baseInterfaceManager bean添加依赖注入,并使用它按顺序遍历实现类:

class FooService {

   def baseInterfaceManager

   void someMethod() {
      for (impl in baseInterfaceManager.orderedImpls) {
         impl.doSomething()
      }
   }
}