Spring中XML,註解,JavaConfig如何選擇

前言

Spring的IOC極大的方便了咱們的編程,當咱們須要某個對象的時候,不在須要本身去new,只要告訴Spring一聲,Spring就會把咱們所須要的類準備好,就像你原來出門要穿外套時,你得先跑到衣櫃前取出衣服,而後本身穿上。如今好了,你結婚了,只要跟你的另外一半說一聲,她就會心照不宣,把衣服給你拿過來,而後幫你穿上,是否是感受很爽?Spring有三種配置方法,這三種配置方式如何選擇?先看一下這三種配置方式html

XML

applicationContext.xmlspring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="knight" class="com.st.BraveKnight">
		<constructor-arg ref="weapon"/>
	</bean>

	<bean id="weapon" class="com.st.Weapon">
		<property name="type" value="knife"/>
	</bean>
</beans>
複製代碼

BraveKnight編程

public class BraveKnight {

    private Weapon weapon;

    public BraveKnight(Weapon weapon) {
        this.weapon = weapon;
    }

    public Weapon getWeapon() {
        return weapon;
    }
}
複製代碼

Weaponbash

public class Weapon {

    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
複製代碼
public class Main {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BraveKnight knight = context.getBean(BraveKnight.class);
        // knife
        System.out.println(knight.getWeapon().getType());
        context.close();
    }
}
複製代碼

這樣一個Spring項目就完成了,能夠用spring的test模塊,進行測試app

@RunWith(SpringJUnit4ClassRunner.class)
// 多個文件時可用locations = {"", ""}
@ContextConfiguration(locations = "classpath*:/applicationContext.xml")
public class XMLTest {

    @Autowired
    BraveKnight braveKnight;

    @Test
    public void test() {
        // knife
        System.out.println(braveKnight.getWeapon().getType());
    }
}
複製代碼

用XML形式能夠在配置文件中,配置咱們本身寫的類和外部庫的類,Spring經過反射能夠把這些類都建立出來,並由Spring管理,在你須要的時候給你工具

註解

BraveKnight測試

@Component
public class BraveKnight {

    @Autowired
    private Weapon weapon;

    public Weapon getWeapon() {
        return weapon;
    }
}
複製代碼

Weaponui

@Component
public class Weapon {

    @Value("knife")
    // 這個值能夠從外部配置文件中經過@Value註解讀取到
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
複製代碼

MyConfigthis

@Configuration
// 若是不配置掃描的路徑,默認掃描配置類所在的包及其子包下面的全部類
@ComponentScan
public class MyConfig {
}
複製代碼
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(MyConfig.class);
        context.refresh();
        BraveKnight knight = context.getBean(BraveKnight.class);
        // knife
        System.out.println(knight.getWeapon().getType());
        context.close();
    }
}
複製代碼
@RunWith(SpringJUnit4ClassRunner.class)
// 從類中讀取配置
@ContextConfiguration(classes = MyConfig.class)
public class AnnotaionTest {

    @Autowired
    BraveKnight braveKnight;

    @Test
    public void test() {
        // knife
        System.out.println(braveKnight.getWeapon().getType());
    }
}
複製代碼

JavaConfig

在咱們本身的類上,咱們能夠加@Component註解讓Spring來管理,若是是第三方jar包的類呢?它的類上並不會加@Component啊,若是不想用XML來生成第三方jar包的類,JavaConfig在這個時候就派上用場了,接着上面的例子,假如Weapon這個類是第三方jar包的類,則能夠經過以下形式讓Spring管理spa

@Configuration
// 若是不配置掃描的路徑,默認掃描配置類所在的包及其子包下面的全部類
// 能夠經過屬性basePackages = {""}指定掃描的包
@ComponentScan()
public class MyConfig {

    // name屬性默認是方法名,本身能夠指定
    @Bean(name = "weapon")
    public Weapon weapon() {
        Weapon weapon = new Weapon();
        weapon.setType("knife");
        return weapon;
    }
}
複製代碼
  1. XML配置修改後不用從新編譯,能夠用於常常切換實現類的對象
  2. 註解用起來很是地簡潔,代碼量十分少,所以是項目的第一選擇
  3. 當須要注入代碼不是本身維護的第三方jar包中的類時,或者須要更爲靈活地注入,好比說須要調用某個接口,查詢數據,而後把這個數據賦值給要注入的對象,那麼這時候就須要用到Java Config

後記

說一個我在用Spring集成Storm遇到的一個有意思的問題,通常想讓外部庫的類讓Spring管理的方法,只要用XML或者JavaConfig配置便可,我項目中有一個ClassA須要繼承Storm中的一個ClassB,可是ClassB是一個抽象類,不能在XML中配置,也不能在JavaConfig中建立出來,直接在ClassA上加上@Component註解,並不能讓Spring管理ClassA,由於ClassB Spring管理不到,Spring不能管理ClassA,這樣就會致使ClassC注入失敗

@Component
public class ClassA extends ClassB {

    @Autowired
    ClassC classC;
}
複製代碼

可能會有人想,直接new出來不就好了,奈何ClassC是以下形式

@Component
public class ClassC{

    @Autowired
    ClassD classD;
}
複製代碼

直接new出來,ClassD就不會被Spring注入進去,怎麼辦?回頭看在啓動類,這個類也沒有被Spring管理,是怎麼取到對象的?是從context中經過getBean方法拿的,可是在其餘的類中怎麼獲取到context,其實Spring提供了一系列Aware接口,只要實現這些接口,就能獲取到要東西,咱們只要實現ApplicationContextAware接口,就能夠獲取到context,爲了方便我直接封裝了一個工具類,經過

SpringHellper.get(ClassC.class)
複製代碼

便可獲取Spring管理的ClassC,並能在ClassA中愉快的使用了

@Component
public class SpringHelper implements ApplicationContextAware {

    private static ApplicationContext context;

    public static ApplicationContext getApplicationContext() {
        return context;
    }
    
    public static <T> T getBean(Class<T> requiredType) {
        return context.getBean(requiredType);
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
}
複製代碼

注意要加上Component註解,這樣在Spring啓動後這個類的context屬性就被填充進來了

參考博客

[1]https://zhuanlan.zhihu.com/p/29938139 [2]https://www.cnblogs.com/hedongfei/p/7899775.html

歡迎關注

喜歡本文的朋友們,歡迎關注公衆號Kruskal,收看更多精彩內容

avatar
相關文章
相關標籤/搜索