如何获得由FactoryBean spring创建的bean?

时间:2011-02-11 14:44:20

标签: java spring autowired

FactoryBean可用于以编程方式创建可能需要复杂实例化逻辑的对象。

但是,似乎FactoryBean创建的bean 并未成为弹簧管理。这种解释是否正确?如果是这样,有什么好的解决方法吗?包含一个简短的代码示例来说明我的问题。

的ApplicationContext:

<bean id="searcher" class="some.package.SearcherFactory" /> 
<bean id="service" class="some.package.Service" /> 

工厂实施:

public class SearcherFactory implements FactoryBean<Searcher> {

    @Override
    public Searcher getObject() throws Exception {
        return new Searcher(); // not so complex after all ;)
    }

    @Override
    public Class<Searcher> getObjectType() {
        return Searcher.class;
    }
    .... 
}

工厂创建的类:

public class Searcher() {
      private Service service;

      @Autowired
      public void setService(Service service) {
           // never invoked
           this.service=service;
      } 
}

6 个答案:

答案 0 :(得分:29)

这是一个为您自动装配的抽象FactoryBean实现:

public abstract class AbstractAutowiringFactoryBean<T> extends
    AbstractFactoryBean<T> implements ApplicationContextAware{

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(
        final ApplicationContext applicationContext){
        this.applicationContext = applicationContext;
    }

    @Override
    protected final T createInstance() throws Exception{
        final T instance = doCreateInstance();
        if(instance != null){
            applicationContext
              .getAutowireCapableBeanFactory()
              .autowireBean(instance);
        }
        return instance;
    }

    /**
     * Create the bean instance.
     * 
     * @see #createInstance()
     */
    protected abstract T doCreateInstance();

}

扩展它,实施getObjectType()doCreateInstance()方法,然后启动并运行自动装配。

注意:未应用BeanPostProcessors,这需要额外的代码。

答案 1 :(得分:20)

FactoryBean 创建的对象由管理,但不由Spring实例化或配置。使用FactoryBean,您自己负责。所有注入和配置必须由FactoryBean

处理

有一种替代方案可能更适合您 - 使用annotation-based config instead of XML-based config。这意味着您可以在Java中使用复杂的实例化逻辑,同时仍然在对象本身上使用@Autowired之类的东西。

我倾向于为所有非平凡的Spring应用程序使用注释样式配置,它使许多事情变得更容易。

答案 2 :(得分:18)

这个怎么样?

<bean id="serviceFactory"
      class="some.package.SearcherFactory" />


<bean id="service"
      factory-bean="serviceFactory"
      factory-method="getObject"/>

...然后只需注入bean'service'而不关心代码中的工厂

答案 3 :(得分:4)

手动方式是:

  1. 在工厂bean中注入依赖项
  2. 在目标对象上手动设置它们。
  3. 您还可以在工厂bean中注入ApplicationContext(或通过实施ApplicationContextAware获取),并执行ctx.getAutowireCapableBeanFactory().autowireBean(bean)

    我承认他们都感到奇怪。

    但事实上,如果逻辑很简单(只是实例化),请使用prototype范围。

答案 4 :(得分:0)

FactoryBean是一个接口,您作为开发人员在编写工厂类时实现,并且您希望工厂类创建的对象由Spring作为bean管理,而另一方面BeanFactory表示Spring IoC容器,它包含托管bean并提供检索它们的权限。它是框架核心的一部分,它实现了控制容器反转的基本功能。

在大多数情况下,您不会发现自己直接使用或实现BeanFactory接口,除非您正在扩展框架的核心功能。当您拥有需要由Spring管理的Factories创建的对象时,您将实现FactoryBean。

用更简洁的话来说,BeanFactory表示Spring容器,而FactoryBean表示工厂类,其创建的对象被拾取并在容器中注册为bean。

public class Neighborhood
{
    public IEnumerable<House> Houses { get; set; }
}

public class House
{
    public Address Address { get; set; }
    public IEnumerable<Room> Rooms { get; set; }
}

public class Room
{
    public IEnumerable<Furniture> Furniture { get; set; }
}

答案 5 :(得分:-4)

不,FactoryBean创建的bean也由spring管理。