Spring - 在配置中使用工厂bean?

时间:2011-06-22 21:35:52

标签: java hibernate spring

@Configuration类中使用工厂bean的正确方法是什么?

假设我有SessionFactory的以下内容:

@Bean
public AnnotationSessionFactoryBean sessionFactory() {
    AnnotationSessionFactoryBean factory = new AnnotationSessionFactoryBean();
    // set up properties etc.
    return factory;
}

现在,此方法返回一个未实现SessionFactory的bean工厂。如果我在@Autowired作为SessionFactory的另一个bean中使用它,它可以正常工作并从bean工厂获得它:

@Controller
public class MyController {
    @Autowired SessionFactory sessionFactory;
    // ...
}

我猜没关系。

但是,如果我想在同一个配置类中使用SessionFactory,那就成了一个问题:

@Bean
public HibernateTransactionManager transactionManager() {
    HibernateTransactionManager man = new HibernateTransactionManager();
    // Ideal - doesn't work because sessionFactory() return type doesn't match:
    // SessionFactory sessionFactory = sessionFactory();
    // Is this one correct?
    // SessionFactory sessionFactory = (SessionFactory) sessionFactory().getObject();
    man.setSessionFactory(sessionFactory);
    return man;
}

实现这种依赖的正确方法是什么?

3 个答案:

答案 0 :(得分:21)

@Configuration方法仍然比较新鲜,并且有一些粗糙的边缘。工厂豆是其中之一。所以不是正确的方式,至少我不知道任何。也许未来的Spring版本会以某种方式处理这个案例。现在,这是我的首选方式:

@Bean
public AnnotationSessionFactoryBean sessionFactoryBean() {
    AnnotationSessionFactoryBean factory = new AnnotationSessionFactoryBean();
    // set up properties etc.
    return factory;
}

@Bean
public SessionFactory sessionFactory() {
   return (SessionFactory) sessionFactoryBean().getObject();
}

并在需要时使用sessionFactory()方法。如果您出于某种原因要多次调用sessionFactoryBean().getObject()(例如,当FactoryBean没有返回单例时),请记住使用@Scope注释。否则,Spring将确保仅调用sessionFactory()一次并缓存结果。

Spring足够智能,可以在调用@Bean方法之后和返回bean本身之前执行所有必需的初始化。因此InitializingBeanDisposableBean@PostConstruct等都得到了认可和妥善处理。事实上,我总是发现调用afterPropertiesSet有点黑客,因为这是容器的责任。


另外在Spring Datastore Document - Reference Documentation中建议采用第二种方法,乍一看看起来有些不一致,但效果很好:

@Resource
private Mongo mongo;

@Bean
MongoFactoryBean mongo() {
     return new MongoFactoryBean();
}

因此,工厂是使用@Bean方法创建的,但工厂创建的bean可以使用自动装配字段获取。聪明。

答案 1 :(得分:0)

我在Spring forums上找到了一个例子。

@Bean
public SessionFactory sessionFactory() {
    AnnotationSessionFactoryBean sessionFactoryBean = 
              new AnnotationSessionFactoryBean();
    // ...configuration code here...
    sessionFactoryBean.afterPropertiesSet();
    return sessionFactoryBean.getObject();
}

答案 2 :(得分:0)

您可以通过以下方式使用它:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class LoginServiceTest {

  @Configuration
  public static class Config {

    @Bean
    public HttpInvokerProxyFactoryBean loginServiceProxy() {
      HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
      proxy.setServiceInterface(LoginService.class);
      proxy.setServiceUrl("http://localhost:8080/loginService");
      return proxy;
    }

  }

  @Inject
  private LoginService loginService;

  @Test
  public void testlogin() {
    loginService.login(...);
  }
}