學習過Spring框架的人一定都會聽過Spring的IoC(控制反轉) 、DI(依賴註入)這兩個概念,對於初學Spring的人來說,總覺得IoC 、DI這兩個概念是模糊不清的,是很難理解的, IoC是什麼 Ioc—Inversion of Control,即“控制反轉”,不是什麼技術,而是一種設計思 ...
學習過Spring框架的人一定都會聽過Spring的IoC(控制反轉) 、DI(依賴註入)這兩個概念,對於初學Spring的人來說,總覺得IoC 、DI這兩個概念是模糊不清的,是很難理解的,
IoC是什麼
Ioc—Inversion of Control,即“控制反轉”,不是什麼技術,而是一種設計思想。
在Java開發中,Ioc意味著將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。如何理解好Ioc呢?理解好Ioc的關鍵是要明確“誰控制誰,控制什麼,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”,那我們來深入分析一下:
●誰控制誰,控制什麼:傳統Java SE程式設計,我們直接在對象內部通過new進行創建對象,是程式主動去創建依賴對象;而IoC是有專門一個容器來創建這些對象,即由Ioc容器來控制對 象的創建;誰控制誰?當然是IoC 容器控制了對象;控制什麼?那就是主要控制了外部資源獲取(不只是對象包括比如文件等)。
●為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程式是由我們自己在對象中主動控制去直接獲取依賴對象,也就是正轉;而反轉則是由容器來幫忙創建及註入依賴對象;為何是反轉?因為由容器幫我們查找及註入依賴對象,對象只是被動的接受依賴對象,所以是反轉;哪些方面反轉了?依賴對象的獲取被反轉了。
用圖例說明一下,傳統程式設計如圖2-1,都是主動去創建相關對象然後再組合起來:
當有了IoC/DI的容器後,在客戶端類中不再主動去創建這些對象了,如圖2-2所示:
以上就是簡單的IOC的理解
那麼接下來我們就來實現下我們自己的第一個Spring示例
1.1我們準備一個HelloWord類
package cn.ljy.clazz; public class HelloWord { //名稱 private String name; //性別 private String sex; //年齡 private int age; //體重 private double weight; //準備構造函數 //無參構造 初始化IOC容器時需要 public HelloWord() { } //姓名 性別 年齡的構造 public HelloWord(String name, String sex, int age) { this.name = name; this.sex = sex; this.age = age; } //姓名 性別 體重的構造 public HelloWord(String name, String sex, double weight) { this.name = name; this.sex = sex; this.weight = weight; } public String sayHello(){ return "HelloWord"+name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "HelloWord [name=" + name + ", sex=" + sex + ", age=" + age + ", weight=" + weight + "]"; } }
1.2我們必須得準備一個applicationContext.xml文件
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd "> <!-- 將 HelloWord 類交給Spring容器進行管理--> <!-- 通過屬性的方式傳入參數 --> <bean id="HelloWord" class="cn.ljy.clazz.HelloWord"> <!-- 為參數賦值 --> <property name="name" value="巴黎的雨季"></property> </bean> </beans>
這樣就整理好了第一個配置文件了,然後我們進行一道測試
package cn.ljy.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.ljy.clazz.HelloWord; import cn.ljy.clazz.NewPeople; import cn.ljy.clazz.People; import cn.ljy.clazz.Person; public class MyTest { public static void main(String[] args) { //實例化Spring容器的上下文 (創建IOC容器) ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); //通過ApplicationContext的getBean()方法,根據id來獲取Bean的實例 HelloWord hello = (HelloWord)context.getBean("HelloWord"); //調用HelloWord類中的方法 System.out.println("通過屬性的方式給name賦值:"); String result = hello.sayHello(); System.out.println(result); }
實現結果為:
1.3以上在配置文件中使用的是setter方法依賴註入,接下來我們使用構造器的方式來實現依賴註入
applicationContext.xml
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd "> <!-- 將 HelloWord 類交給Spring容器進行管理--> <!-- 通過構造器的方式傳入參數 --> <bean id="AttributeByConstructor1" class="cn.ljy.clazz.HelloWord"> <!-- 通過構造器方式傳參 --> <constructor-arg value="巴黎的雨季" index="0"/> <constructor-arg value="男" index="1"/> <constructor-arg value="18" type="int"/> </bean> </beans>
執行結果如圖
1.4使用引用類型,引用自定義的Bean(外部Bean)
準備一個person對象
package cn.ljy.clazz; public class Person { private String name; private int age; private Car car; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", car=" + car + "]"; } }
applicationContext.xml
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd "> <!-- 監管Car 準備三car--> <bean id="car" class="cn.ljy.clazz.Car"> <property name="brand" value="賓士"></property> <property name="business" value="上海"></property> <property name="price" value="300000"></property> </bean> <!-- 配置person 引用Car --> <bean id="person" class="cn.ljy.clazz.Person"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="18"></property> <property name="car" ref="car"></property> </bean> </bean> </beans>
執行結果
1.5使用內部Bean
<!-- 內部bean --> <bean id="person2" class="cn.ljy.clazz.Person"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="18"></property> <!-- 註意:內部bean只能在內部使用,不能被外部所引用 --> <property name="car" > <bean class="cn.ljy.clazz.Car"> <property name="brand" value="福特"></property> <property name="business" value="北京"></property> <property name="price" value="400000"></property> </bean> </property> </bean>
執行結果與上一步基本一致
1.6配置list集合屬性
People
package cn.ljy.clazz; import java.util.List; public class People { private String name; private int age; private List<Car> cars; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } @Override public String toString() { return "People [name=" + name + ", age=" + age + ", cars=" + cars + "]"; } }
<!-- list集合屬性的配置 --> <bean id="people" class="cn.ljy.clazz.People"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="28"></property> <property name="cars"> <!-- 使用list節點為集合屬性賦值 --> <list> <ref bean="car"/> <ref bean="car2"/> <ref bean="car3"/> </list> </property> </bean>
執行結果
1.7使用Map集合配置屬性
NewPeople
package cn.ljy.clazz; import java.util.Map; import java.util.Properties; public class NewPeople { private String name; private int age; private Map<String,Car> cars; //配置properties屬性 private Properties properties; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Map<String, Car> getCars() { return cars; } public void setCars(Map<String, Car> cars) { this.cars = cars; } public Properties getProperties() { return properties; } public void setProperties(Properties properties) { this.properties = properties; } @Override public String toString() { return "NewPeople [name=" + name + ", age=" + age + ", cars=" + cars + "]"; } }
<!--Map集合屬性值的配置 --> <bean id="people2" class="cn.ljy.clazz.NewPeople"> <property name="name" value="巴黎的雨季"></property> <property name="age" value="28"></property> <property name="cars"> <map> <entry key="OneCar" value-ref="car"></entry> <entry key="TwoCar" value-ref="car2