(1)、概念:把對象的建立、初始化、銷燬等工做交給Spring來作java
(2)、Hello Worldspring
首先導入必須的jar包數據庫
接着建立bean容器配置文件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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- hello world --> <bean id="helloworld" class="ff.helloworld.HelloWorld"></bean> </beans>
<beans>元素中屬性是一些必要的約束,<bean>元素描述某個類,id屬性是bean惟一標識,class屬性是類的全限定名安全
而後建立HelloWorld類和測試類,進行測試session
public class HelloWorld { public void say() { System.out.println("Hello World -Spring"); } }
public class TestHelloWorld { private ApplicationContext applicationContext; @Before /** * 加載context */ public void init() { applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); } @Test public void testSay() { HelloWorld hw = (HelloWorld) applicationContext.getBean("helloworld"); hw.say(); } }
加載配置文件applicationContext.xml生成ApplicationContext對象,再用它的getBean()方法從bean容器中獲取helloworld對象,調用say()方法。
app
(3)、Spring建立對象的三種方式
框架
a、構造器(用的最多)
dom
經過類的構造器建立對象,上面helloworld案例就是經過構造器建立
性能
b、靜態工廠
applicationContext.xml中不配置具體的某個bean,而是配置一個工廠bean,在建立工廠bean的時候調用工廠方法(factory-method)建立具體bean。
<!-- 靜態工廠建立bean --> <bean id="beanDemoFactory_static" class="ff.beanCreate.BeanDemoFactory_Static" factory-method="getInstance" lazy-init="true"></bean>
public class BeanDemo { public BeanDemo() { System.out.println("i am BeanDemo"); } public void say() { System.out.println("i am created!"); } }
public class BeanDemoFactory_Static { public static BeanDemo getInstance() { return new BeanDemo(); } }
c、實例工廠
application中不配置具體某個bean,而是配置一個工廠bean同時配置一個第三方bean,在建立第三方bean的時候經過factory-bean屬性找到工廠bean,再調用工廠方法(factory-method屬性)建立具體bean。
<!-- 實例工廠建立bean --> <bean id="beanDemoFactory_instance" class="ff.beanCreate.BeanDemoFactory_instance"></bean> <!-- 第三方bean --> <bean id="beanDemo_instance" factory-bean="beanDemoFactory_instance" factory-method="getInstance"></bean>
public class BeanDemo { public BeanDemo() { System.out.println("i am BeanDemo"); } public void say() { System.out.println("i am created!"); } }
public class BeanDemoFactory_instance { public BeanDemo getInstance() { return new BeanDemo(); } }
d、爲何要用工廠方式建立對象?
實現bean建立和使用分離,將bean建立的工做交由工廠來完成。這樣能夠統一管理bean的建立,如能夠在各個bean建立前作一些初始化工做。此外,便於集成其它框架的bean建立管理方法。
(4)、Spring建立對象的時機
Spring默認在啓動IoC容器時自動建立對象,但能夠經過配置<bean>元素的lazy-init屬性自定義建立時機。
lazy-init屬性有三種值:default、false、true。默認值爲default,效果等同於值false,在啓動時建立對象,若將其設置爲true則在獲取bean的時候建立對象。
注意:通常不設置爲true,緣由是這樣設置後Spring在啓動不會建立這個bean,若是這個bean有bug,那麼啓動時不會報錯,致使存在安全隱患。若一個bean的屬性中含有大量數據,過早的放入內存會影響程序性能,這時候將lazy-init設置爲ture。
(5)、bean的scope(做用域)
a、 默認狀況
默認狀況下Spring建立的bean是單例的,每次獲取bean的時候返回同一個對象,這個bean的屬性天然也被多處引用中共享,這樣很不安全。因此默認狀況下不能將數據定義到bean屬性中。
b、修改bean的scope
<bean>元素中的scope屬性能夠修改scope。scope屬性有四個值singleton(單例)、prototype(多例)、request、session,其中prototype爲原型模式,每次獲取bean返回不一樣對象。
c、選擇單例仍是多例?
Spring IoC容器在啓動時會建立applicationContext.xml文件中配置的全部bean,實際開發中大多數的bean只會使用到1次,因此默認配置爲單例,對特殊bean配置成多例。
(6)、scope與建立時機的結合
a、當scope爲property時,無論lazy-init值是什麼,都在獲取bean的時候建立對象。由於property是多例模式,每次獲取bean的時候都會返回不一樣的對象。
b、當scope爲singleton時,在何時建立對象由lazy-init決定,且都以單例模式建立。
(7)、bean初始化,銷燬
<bean>元素的init-method和destory-method定義初始化和銷燬方法。
(8)、bean建立、初始化、銷燬的順序
當Spring啓動(或代碼中獲取bean)時建立bean對象,接着Spring內部調用初始化方法(若是配置),當Spring容器關閉時執行這個bean對象的銷燬方法。
說明:一、初始化和銷燬方法由Spring內部執行。 二、銷燬方法在Spring容器關閉時執行,但Spring容器通常不會關閉,因此容器裏的對象會一直存在。三、若是<bean>元素的scope屬性值爲property,Spring容器不負責銷燬。
(1)、概念:給bean對象屬性賦值
(2)、三種賦值方式
a、經過setter方法賦值
配置<bean>元素內<property>子元素,在bean被建立時調用對應的setter方法給屬性注入值。
<bean id="persion" class="domain.Persion"> <property name="student" ref="student"></property> <property name="string" value="this is a string"></property> <property name="list"> <list> <value>index1</value> <value>index2</value> <ref bean="student"/> </list>s </property> </bean>
public class Persion { private Student student; // Student對象 private String string; private List list; public void say(Student student) { student.say(); } public void setStudent(Student student) { this.student = student; } public void setString(String string) { this.string = string; } public void setList(List list) { this.list = list; } }
當Person對象被建立時,Spring經過<property>元素找到對應的setter方法,將配置的值注入。
<property>元素給屬性注入值,value爲基本類型以及String類型值,ref爲引用屬性的bean的id,array、list、map爲集合屬性
b、經過構造方法賦值
在<bean>元素內配置<constructor-arg>元素,當Persion類被建立時調用對應的構造器爲屬性賦值。
<bean id="student" class="ff.ing.pojo.Student"> <constructor-arg index="0" value="蓋倫"></constructor-arg> </bean> <bean id="persion" class="ff.ing.pojo.Persion"> <constructor-arg index="0" value="007"></constructor-arg> <constructor-arg index="1" value="趙信"></constructor-arg> <constructor-arg index="2" ref="student"></constructor-arg> </bean>
public class Persion { private int id; private String name; private Student student; public Persion() { } public Persion(int id, String name, Student student) { this.id = id; this.name = name; this.student = student; } public void say() { String str = "id:" + id + " name:" + name + " student:" + student.getName(); System.out.println(str); } }
index屬性爲構造器參數列表中參數的序號。
c、經過註解賦值
一、依賴注入註解
(1) 首先須要修改applicationContext.xml文件:添加註解命名空間約束,啓動依賴注入註解解析器
<!-- 添加註解命名空間約束 --> xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 啓動依賴注入註解解析器 --> <context:annotation-config/> <!-- bean --> <bean>........</bean>
(2) 在類中使用註解
public class Persion { private int id; private String name; @Resource(name="student") private Student student; ……… ……… }
@Resource會到IoC容器中尋找id與name匹配的bean,賦值給student屬性。
@Resource是java內置註解,Spring框架定義了本身的註解。@Autowired按照類型進行匹配;@Qualifier(value="xxx")按照id進行匹配,且只能與@Autowired組合使用,沒法單獨使用。
註解只能注入引用類型值,沒法注入基本類型、String類型以及集合類型值
註解方式比xml配置方式效率低。
二、類掃描註解
(1)、首先須要修改applicationContext.xml文件:添加註解命名空間約束,啓動類掃描註解解析器,配置要掃描的包
<!-- 添加註解命名空間約束 --> xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 啓動類掃描註解解析器,配置要掃描的包 --> <context:component-scan base-package="ff.ing.pojo"></context:component-scan>
(2)在類中使用註解
@Component(value="student") public class Student { private String name; public Student() { } …… …… } @Component(value="persion") public class Persion { private int id; private String name; @Resource(name="student") private Student student; public Persion() { } …… …… }
@Component配置了這個類的在spring容器中的id,以Persion類爲例@Component(value="persion")至關於<bean id="persion" class="……"></bean>
Spring還提供了更細分的組件註解:@Repository
、@Service
和 @Controller,分別表明dao層、業務層和控制層。他們的用法以及功能與@Component一致,只是方便了代碼的閱讀而已。
類掃描註解方式比依賴注入註解方式效率還低。
● IoC、DI中的類繼承問題
當使用setter和構造器方法給屬性輸入值時,子類沒法繼承父類中屬性的值,這時須要在<bean>元素中添加parent屬性。使用註解不存在這樣的問題
● IoC與DI的意義
● IoC與DI最生動的解釋(摘抄他人)
首先想說說IoC(Inversion of Control,控制倒轉)。這是spring的核心,貫穿始終。所謂IoC,對於spring框架來講,就是由spring來負責控制對象的生命週期和對象間的關係。這是什麼意思呢,舉個簡單的例子,咱們是如何找女友的?常見的狀況是,咱們處處去看哪裏有長得漂亮身材又好的mm,而後打聽她們的興趣愛好、號碼………,想辦法認識她們,投其所好送其所要,而後嘿嘿……這個過程是複雜深奧的,咱們必須本身設計和麪對每一個環節。傳統的程序開發也是如此,在一個對象中,若是要使用另外的對象,就必須獲得它(本身new一個,或者從JNDI中查詢一個),使用完以後還要將對象銷燬(好比Connection等),對象始終會和其餘的接口或類藕合起來。
那麼IoC是如何作的呢?有點像經過婚介找女友,在我和女友之間引入了一個第三者:婚姻介紹所。婚介管理了不少男男女女的信息,我能夠向婚介提出一個列表,告訴它我想找個什麼樣的女友,好比長得像李嘉欣,身材像林熙雷,唱歌像周杰倫,速度像卡洛斯,技術像齊達內之類的,而後婚介就會按照咱們的要求,提供一個mm,咱們只須要去和她談戀愛、結婚就好了。簡單明瞭,若是婚介給咱們的人選不符合要求,咱們就會拋出異常。整個過程再也不由我本身控制,而是有婚介這樣一個相似容器的機構來控制。Spring所倡導的開發方式就是如此,全部的類都會在spring容器中登記,告訴spring你是個什麼東西,你須要什麼東西,而後spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其餘須要你的東西。全部的類的建立、銷燬都由 spring來控制,也就是說控制對象生存週期的再也不是引用它的對象,而是spring。對於某個具體的對象而言,之前是它控制其餘對象,如今是全部對象都被spring控制,因此這叫控制反轉。若是你還不明白的話,我決定放棄。
IoC的一個重點是在系統運行中,動態的向某個對象提供它所須要的其餘對象。這一點是經過DI(Dependency Injection,依賴注入)來實現的。好比對象A須要操做數據庫,之前咱們老是要在A中本身編寫代碼來得到一個Connection對象,有了 spring咱們就只須要告訴spring,A中須要一個Connection,至於這個Connection怎麼構造,什麼時候構造,A不須要知道。在系統運行時,spring會在適當的時候製造一個Connection,而後像打針同樣,注射到A當中,這樣就完成了對各個對象之間關係的控制。A須要依賴 Connection才能正常運行,而這個Connection是由spring注入到A中的,依賴注入的名字就這麼來的。那麼DI是如何實現的呢? Java 1.3以後一個重要特徵是反射(reflection),它容許程序在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性,spring就是經過反射來實現注入的。
● 意義
實現了徹底面向接口編程(程序設計依賴於抽象的接口而非具體實現類),在代碼中不須要關心具體是哪一個實現類在工做。