根據彈簧對象的名稱識別它們
不管使用XML還是Java配置都沒有關系,Spring范圍大致類似于Map <String,Object>結構。 這意味著您不能有兩個名稱相同的對象 。 為什么這是一件壞事? 如果您的大型應用程序包含許多@Configuration類或XML文件,則很容易意外地兩次使用相同的名稱。
最糟糕的是,它們與多個對象一起使用時,它們會默默地相互覆蓋,直到實際上只有一個保留在ApplicationContext中為止。 這些對象也可以是不同的類型,而聲明順序才是真正確定哪個對象獲勝的因素。 這里的問題是,如果您想基于Spring創建可重用的模塊,則基本上將被迫在名稱或其他名稱中使用前綴,以確保不會出現名稱沖突。
根據對象的類別識別Guice對象
Guice范圍基本上類似于Map <Class <?>,Object>結構。 這意味著如果不使用額外的元數據(例如,限定詞), 就不能擁有兩個相同類型的對象 。 這種設計選擇有不同的優缺點,但總的來說,我認為這是比較明智??的選擇。 如果創建可重用的模塊,則必須確保不導出任何通用類型的對象(例如,字符串)。 使用基于類型的作用域,您始終可以為常見類型創建一個包裝的類,而使用基于名稱的作用域,您將始終不得不根據幸運的猜測使用唯一的名稱。 Guice還具有PrivateModules,因此您可以對所有注入使用Guice,但僅導出范圍中的某些對象。 ?
范例程式碼
這是一個Spring應用程序的幼稚示例,由于無聲Bean覆蓋而中斷了運行時。
Main.java
此類實例化應用程序上下文,注冊配置類并嘗試從上下文中獲取MyBean。
package springbreak;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Main {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();ctx.register(GoodConfig.class);ctx.register(EvilConfig.class);ctx.refresh();ctx.start();System.out.println(ctx.getBean(MyBean.class).getValue());ctx.stop();}
}
MyBean.java
這只是我們期望從應用程序上下文中獲得的一種示例類型的Bean。
package springbreak;public interface MyBean {String getValue();
}
GoodConfig.java
這是一個導出MyBean的配置類
package springbreak;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class GoodConfig {private static class MyBeanImpl implements MyBean {public String getValue() {return "I'm a bean";}}@Beanpublic MyBean myBean() {return new MyBeanImpl();}}
EvilConfig.java
此配置類導出名為myBean的String。 這不是一個非常現實的示例,但顯示了基本思想。
package springbreak;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class EvilConfig {@Beanpublic String myBean() {return "I'm a string!";}}
分析例子
您可以猜測運行示例時會發生什么嗎? 這是基本思想:
- GoodConfig導出名稱為“ myBean”的MyBeanImpl。
- 即使類型不匹配 ,EvilConfig 也會導出一個名稱為“ myBean”的字符串替換GoodConfig中的字符串
- Main獲得NoSuchBeanDefinitionException“未定義[springbreak.MyBean]類型的唯一bean”
因此,基本上將MyBeanImpl替換為String,并且不會有實現MyBean的bean。 最糟糕的部分是, 如果您顛倒@Configuration類的注冊順序,該代碼將起作用,因為然后String將被MyBeanImpl替換。 現在,假設您有20個封裝良好的模塊,這些模塊的名稱可能會發生沖突……我已經多次碰壁,試圖在這種情況下調試問題。
Spring(從3.0.6版開始)無法更改@Configuration類導出的bean的命名。 如果要創建可安全重用的模塊,則必須在導出Bean的方法中使用某種完全限定的名稱(例如goodConfigMyBean,evilConfigMyBean)。
我喜歡Spring(尤其是非DI容器部件),但是在新項目中,我將拒絕使用從根本上被破壞的庫。 是的,兩次使用相同的名稱是開發人員錯誤,但是容易出現此類錯誤的任何庫都可被認為比嘗試最小化這些錯誤的替代方法更糟。
參考: Spring vs Guice: Jawsy Solutions技術博客博客上我們JCG合作伙伴 Joonas Javanainen的重要差異之一 。
翻譯自: https://www.javacodegeeks.com/2012/06/spring-vs-guice-one-critical-difference.html