2012-11-27 19 views
4

如果我使用@Bean聲明一個類,然後對該類進行組件掃描,那麼spring將通過調用它的構造函數並注入構造函數參數來實例化該類,並注入標記爲@注入。爲了簡單起見,我們稱之爲自動建設。Spring批註 - @調用spring bean自動構建

我不喜歡組件掃描,並希望完全避免它(我不想討論我不喜歡它的原因)。我想使用一個@Configuration對象,但仍然希望自動構建功能可用。是否有可能調用spring來自動構建我的對象,而不是顯式地傳遞我的@Configuration對象中的所有構造函數參數?

讓我們假設我有一顆豆:

public class MyServiceImpl implements MyService { 
    public MyServiceImpl(Dependency1 d1, Dependency d2) { ... } 
    .... 
} 

我可以定義一個配置對象是這樣的:

@Configuration 
public class MyConfiguration { 
    // lets assume d1 and d2 are defined in another @Configuration 
    @Inject 
    Dependency1 d1; 

    @Inject 
    Dependency2 d2; 

    @Bean 
    public MyService myService() { 
     // I dislike how I have to explicitly call the constructor here 
     return new MyServiceImpl(d1, d2); 
    } 
} 

但現在,我已經明確只好打電話給MyServiceImpl構造器自己,所以我將不得不隨着我的構造函數隨着時間的推移而不斷更新。

我希望我可以宣佈一個抽象的方法,使彈簧自動建築物可能發生:

@Configuration 
public abstract class MyConfiguration { 
    @Bean 
    public abstract MyServiceImpl myService(); 
} 

但是,這是行不通的。有沒有辦法可以調用彈簧自動編制沒有使用組件掃描?

在谷歌吉斯,這可以通過活頁夾來完成: http://tapestry.apache.org/ioc-cookbook-basic-services-and-injection.html#IoCCookbook-BasicServicesandInjection-SimpleServices

更新

基於SPOD的: https://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/Binder.html

在Tapestry IOC,這可以通過的ServiceBinder完成回答,我能夠實現我以後的(謝謝!)。包括爲任何人想要做同樣的測試情況:

import java.util.Date; 
import javax.inject.Inject; 
import junit.framework.Assert; 
import org.junit.Test; 
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 

public class AutoBuildConfigurationTest { 
    @Configuration 
    public static class MyConfiguration { 
     @Inject 
     private AutowireCapableBeanFactory beanFactory; 

     @Bean 
     public Date date() { 
      return new Date(12345); 
     } 

     @Bean 
     public MyService myService() { 
      return autoBuild(MyService.class); 
     } 

     protected <T> T autoBuild(Class<T> type) { 
      return type.cast(beanFactory.createBean(type, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true)); 
     } 
    } 

    public static class MyService { 
     private Date date; 

     public MyService(Date date) { 
      this.date = date; 
     } 

     public Date getDate() { 
      return date; 
     } 
    } 

    @Test 
    public void testAutoBuild() { 
     ApplicationContext appContext = new AnnotationConfigApplicationContext(MyConfiguration.class); 
     MyService myService = appContext.getBean(MyService.class); 
     Assert.assertEquals(12345, myService.getDate().getTime()); 
    } 
} 

回答

7

基於Java容器配置犯規依賴於以任何方式做一個組件掃描。它對於基於XML的組件配置僅僅是一種不同的方法。使用XML配置,您只需用MyServiceImpl類聲明bean,以防注入已注入的@inject。春天會認出註釋並照顧他們。如果你真的想實例化從@Configuration java類MyServiceImpl沒有自己調用構造函數,那麼你就必須利用bean工廠的(還沒有測試它,只要給它一試):

@Configuration 
public class MyConfiguration { 

    @Autowired AutowireCapableBeanFactory beanFactory; 

    @Bean public MyService myService() { 
     return beanFactory.createBean(MyServiceImpl.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true); 
    } 
} 
+0

我意識到註釋配置不需要組件掃描,但我希望組件掃描使用的自動構建功能。你的迴應讓我看到了一段代碼,負責autobuild。謝謝! –