2011-06-22 49 views
12

什麼是在@Configuration類中使用工廠bean的正確方法?春天 - 在配置中使用工廠bean?

假設爲SessionFactory我有以下幾點:

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

現在這個方法返回一個bean工廠,沒有實現SessionFactory。如果我在@AutowiredSessionFactory另外一個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; 
} 

什麼是正確的方式來實現這種依賴?

回答

20

@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本身之前足夠智能地執行所有必需的初始化。所以InitializingBean,DisposableBean,@PostConstruct等都被正確識別和處理。事實上,我總是認爲致電afterPropertiesSet有點黑客,因爲它是集裝箱的責任。


也有是在Spring Datastore Document - Reference Documentation建議第二種方法,乍一看看起來有點不協調,但偉大工程:

@Resource 
private Mongo mongo; 

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

所以工廠使用@Bean方法創建,但豆由創建工廠可以使用autowired字段獲得。聰明。

+0

不要求它的afterPropertiesSet()? –

+0

不,Spring在調用'@ Bean'方法之後和返回bean本身之前足夠智能地執行所有必需的初始化。所以'InitializingBean','DisposableBean','@ PostConstruct'等都被正確識別和處理。事實上,我總是發現調用'afterPropertiesSet'有點破解,因爲它是容器的責任。 –

+1

另外,請參閱我的編輯,我找到了另一個解決方案。 –

0

我在Spring forums上找到了一個這樣的例子。

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

這是一個壞主意。如果你這樣做,FactoryBean的生命週期將不會按照它的原樣進行管理,並且你的應用程序不會乾淨地關閉。在這個特定的例子中,你可以通過使用@Bean(destroyMethod =「close」)來避免這個問題,但它並不好。 – skaffman

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