2014-11-21 31 views
0

我有一個愛好項目,我想遷移到Spring。讓Spring的IoC容器實例化零配置bean(如Google Guice的行爲)

舉個例子,我有以下類別:

public class OtherBean { 
    public void printMessage() { 
     System.out.println("Message from OtherBean"); 
    } 
} 


public class InjectInMe { 
    @Inject OtherBean otherBean; 

    public void callMethodInOtherBean() { 
     otherBean.printMessage(); 
    } 
} 

但是因爲我讀的文件,我必須註解要由Spring與像@Component註釋管理的所有類別(或其他人是相似的) 。

用下面的代碼運行它:

public class SpringTest { 
    public static void main(String[] args) { 
     AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 
     context.refresh(); 

     InjectInMe bean = context.getBean(InjectInMe.class); 
     bean.callMethodInOtherBean(); 
    } 
} 

給我的錯誤:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [somepackage.InjectInMe] is defined 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:371) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331) 
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:968) 
    at somepackage.SpringTest.main(SpringTest.java:10) 

我的問題是:有沒有一種方法,使春季管理任何類我問的ApplicationContext實例沒有我必須註冊他們在一個註釋的配置(或XML配置)?

在吉斯我可以注入類

public class GuiceTest { 
    static public class GuiceConfig extends AbstractModule { 

     @Override 
     protected void configure() {} 

    } 
    public static void main(String[] args) { 
     Injector injector = Guice.createInjector(new GuiceConfig()); 
     InjectInMe bean = injector.getInstance(InjectInMe.class); 
     bean.callMethodInOtherBean(); 
    } 
} 

給我的輸出:

Message from OtherBean 

反正我有可以使彈簧的工作像吉斯?就像在春天注入我的豆沒有我不得不註冊或掃描包@類標註批註類的包?

任何春季大師有辦法解決這個問題?

回答

2

My question is: is there a way to make Spring manage any class I ask the ApplicationContext to instantiate without me having to register them in an Annotated Config (or XML config)?

不,這是不可能的。這根本不是Spring設計的方式。您必須隱式地(例如,掃描+註釋)或顯式地(例如XML bean定義)註冊您的bean。

你至少能做的是一樣的東西:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 
context.register(OtherBean.class); 
context.register(InjectInMe.class); 
context.refresh(); 
+0

感謝您的回答,我調試了Spring的AnnotationConfigApplicationContext,並且發現沒有簡單的方法來添加這種類Guice行爲。我暫時堅持Guice,因爲我不會註冊所有**我的課程。我希望春天在未來給我們一個選擇。 – 2014-11-21 21:35:37

0

有幾種方式爲Spring的ApplicationContext提供bean定義:

  1. 使用組件掃描,並與@Component或其元註解之一來註解你的類型(@Service@Controller等)
  2. 定義XML配置中的<bean>或Java配置中的@Bean(或任何其他類型的顯式配置)。
  3. 使用BeanDefinitionRegistryPostProcessor直接在BeanDefinitionRegistry上註冊bean。
  4. 一些ApplicationContext子類型實現BeanDefinitionRegistry,所以你可以直接註冊它們的bean定義。

當需要注入時,從這些bean定義生成的bean將可用。你不希望(至少是IMO)你的容器實例化一個類型,但你不知道它是否可以。

+0

謝謝您的回答,我加粗體我的問題 – 2014-11-21 20:00:48

+0

最相關的部分,我添加的代碼作爲例子,使問題更加清晰 – 2014-11-21 21:02:30

+0

@discipline對。這就是我最後一句話暗示的。我覺得Guice正在做的事很危險。你沒有明確告訴它如何獲得一個'OtherBean'實例。 Guice決定實例化類型時,您可能會得到非常意想不到的行爲。 – 2014-11-21 22:10:41

0

您必須將該類聲明爲@Component,或者不管它是什麼,或者您必須提供一個xml定義。如果你沒有定義這個bean,那Spring應該怎麼知道該怎麼做?對於課程的屬性,例如MyController有一個私人服務MyService。如果你把@Autowired標籤放在服務實例上面,Spring會自動將這個服務器注入到你的控制器中,這就是你對@Inject的評論似乎提示的內容。但是,爲了自動裝配,您必須爲該類定義一個bean,這意味着您必須使用@ Component/@ Controller等註釋配置或xml bean配置。

+0

「如果你沒有定義,春天應該知道該怎麼做?」 - 試圖像Google Guice那樣實例化它?謝謝你嘗試回答它。 – 2014-11-21 19:59:32

+0

通過添加Inject標籤,您可以添加某種註釋,從而讓Guice知道該怎麼做。這同樣適用於Spring,但不是Inject標籤,而是使用@Autowire – holtc 2014-11-21 20:12:18

+0

我添加了代碼作爲示例。再次感謝你的時間。也許這個問題更清楚的例子:-)我想知道我是否可以在Spring中模仿Guice的「Just Works(tm)」行爲 – 2014-11-21 20:57:00