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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6446857/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:54:56  来源:igfitidea点击:

Spring - using factory beans in configuration?

javahibernatespring

提问by Konrad Garus

What is the correct way to use factory beans in @Configurationclasses?

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

Suppose I have the following for SessionFactory:

假设我有以下内容SessionFactory

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

Right now this method returns a bean factory which does not implement SessionFactory. If I use it in another bean with @Autowiredas SessionFactory, it works just fine and obtains it from bean factory:

现在这个方法返回一个没有实现的 bean 工厂SessionFactory。如果我在另一个带有@Autowiredas 的bean 中使用它SessionFactory,它就可以正常工作并从 bean 工厂获取它:

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

I guess that's OK.

我想没关系。

However, it becomes an issue if I want to use the SessionFactoryin the same configuration class:

但是,如果我想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;
}

What is The Right Way to implement this kind of dependency?

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

回答by Tomasz Nurkiewicz

@Configurationapproach is still relatively fresh and it has some rough edges. Factory beans are one of them. So the is no Right Way, at least I am not aware of any. Maybe future Spring releases will handles this case somehow. For now, this is my preferred way:

@Configuration方法还是比较新鲜的,有一些粗糙的地方。工厂豆就是其中之一。所以没有正确的方法,至少我不知道。也许未来的 Spring 版本会以某种方式处理这种情况。目前,这是我的首选方式:

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

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

And use sessionFactory()method whenever needed. If you want to call the sessionFactoryBean().getObject()several times for some reason (e.g. when FactoryBeandoes not return singletons), remember to use @Scopeannotation. Otherwise Spring will make sure sessionFactory()is called only once and cache the result.

sessionFactory()在需要时使用方法。如果你sessionFactoryBean().getObject()因为某种原因想要多次调用(例如 whenFactoryBean不返回单例),记得使用@Scope注解。否则 Spring 将确保sessionFactory()只调用一次并缓存结果。

Spring is intelligent enough to perform all required initialization after calling @Beanmethod and before returning the bean itself. So InitializingBean, DisposableBean, @PostConstruct, etc. are all recognized and treated properly. In fact, I was always finding calling afterPropertiesSeta bit of a hack, because it is the container responsibility.

Spring 足够智能,可以在调用@Bean方法之后和返回 bean 本身之前执行所有必需的初始化。因此InitializingBeanDisposableBean@PostConstruct、 等都被正确识别和处理。事实上,我一直觉得调用afterPropertiesSet有点麻烦,因为这是容器的责任。



Also there is a second method advised in Spring Datastore Document - Reference Documentation, which at first sight looks a bit inconsistent, but works great:

Spring Datastore Document - Reference Documentation 中还建议了第二种方法,乍一看有点不一致,但效果很好:

@Resource
private Mongo mongo;

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

So factory is created using @Beanmethod but the bean created by the factory can be obtained using autowired field. Clever.

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

回答by Mark McLaren

I found an example of this on the Spring forums.

我在Spring 论坛上找到了一个这样的例子。

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

回答by Ortwin Angermeier

You can use it the following way:

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

@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(...);
  }
}