spring第一章spring
Spring是一個開源框架,它由Rod Johnson建立。它是爲了解決企業應用開發的複雜性而建立的。Spring使用基本的JavaBean來完成之前只可能由EJB完成的事情。然而,Spring的用途不只限於服務器端的開發。從簡單性、可測試性和鬆耦合的角度而言,任何Java應用均可以從Spring中受益。Spring是一個輕量級的控制反轉(IoC)和麪向切面(AOP)的容器框架。官方下載地址: http://repo.spring.io數據庫
輕量——從大小與開銷兩方面而言Spring都是輕量的。完整的Spring框架能夠在一個大小隻有1MB多的JAR文件裏發佈。而且Spring所需的處理開銷也是微不足道的。此外,Spring是非侵入式的:典型地,Spring應用中的對象不依賴於Spring的特定類。express
控制反轉——Spring經過一種稱做控制反轉(IoC)的技術促進了鬆耦合。當應用了IoC,一個對象依賴的其它對象會經過被動的方式傳遞進來,而不是這個對象本身建立或者查找依賴對象。你能夠認爲IoC與JNDI相反——不是對象從容器中查找依賴,而是容器在對象初始化時不等對象請求就主動將依賴傳遞給它。編程
面向切面——Spring提供了面向切面編程的豐富支持,容許經過分離應用的業務邏輯與系統級服務(例如審計(auditing)和事務(transaction)管理)進行內聚性的開發。應用對象只實現它們應該作的——完成業務邏輯——僅此而已。它們並不負責(甚至是意識)其它的系統級關注點,例如日誌或事務支持。服務器
容器——Spring包含並管理應用對象的配置和生命週期,在這個意義上它是一種容器,你能夠配置你的每一個bean如何被建立——基於一個可配置原型(prototype),你的bean能夠建立一個單獨的實例或者每次須要時都生成一個新的實例——以及它們是如何相互關聯的。然而,Spring不該該被混同於傳統的重量級的EJB容器,它們常常是龐大與笨重的,難以使用。session
框架——Spring能夠將簡單的組件配置、組合成爲複雜的應用。在Spring中,應用對象被聲明式地組合,典型地是在一個XML文件裏。Spring也提供了不少基礎功能(事務管理、持久化框架集成等等),將應用邏輯的開發留給了你。app
核心容器框架
這是Spring框架最基礎的部分,它提供了依賴注入(DependencyInjection)特徵來實現容器對Bean的管理。這裏最基本的概念是BeanFactory,它是任何Spring應用的核心。BeanFactory是工廠模式的一個實現,它使用IoC將應用配置和依賴說明從實際的應用代碼中分離出來。函數
應用上下文(Context)模塊工具
核心模塊的BeanFactory使Spring成爲一個容器,而上下文模塊使它成爲一個框架。這個模塊擴展了BeanFactory的概念,增長了對國際化(I18N)消息、事件傳播以及驗證的支持。
另外,這個模塊提供了許多企業服務,例如電子郵件、JNDI訪問、EJB集成、遠程以及時序調度(scheduling)服務。也包括了對模版框架例如Velocity和FreeMarker集成的支持。
Spring的AOP模塊
Spring在它的AOP模塊中提供了對面向切面編程的豐富支持。這個模塊是在Spring應用中實現切面編程的基礎。爲了確保Spring與其它AOP框架的互用性,Spring的AOP支持基於AOP聯盟定義的API。AOP聯盟是一個開源項目,它的目標是經過定義一組共同的接口和組件來促進AOP的使用以及不一樣的AOP實現之間的互用性。經過訪問他們的站點,你能夠找到關於AOP聯盟的更多內容。
Spring的AOP模塊也將元數據編程引入了Spring。使用Spring的元數據支持,你能夠爲你的源代碼增長註釋,指示Spring在何處以及如何應用切面函數。
JDBC抽象和DAO模塊
使用JDBC常常致使大量的重複代碼,取得鏈接、建立語句、處理結果集,而後關閉鏈接。Spring的JDBC和DAO模塊抽取了這些重複代碼,所以你能夠保持你的數據庫訪問代碼乾淨簡潔,而且能夠防止因關閉數據庫資源失敗而引發的問題。
這個模塊還在幾種數據庫服務器給出的錯誤消息之上創建了一個有意義的異常層。使你不用再試圖破譯神祕的私有的SQL錯誤消息!
另外,這個模塊還使用了Spring的AOP模塊爲Spring應用中的對象提供了事務管理服務。
對象/關係映射集成模塊
對那些更喜歡使用對象/關係映射工具而不是直接使用JDBC的人,Spring提供了ORM模塊。Spring並不試圖實現它本身的ORM解決方案,而是爲幾種流行的ORM框架提供了集成方案,包括Hibernate、JDO和iBATIS SQL映射。Spring的事務管理支持這些ORM框架中的每個也包括JDBC。
Spring的Web模塊
Web上下文模塊創建於應用上下文模塊之上,提供了一個適合於Web應用的上下文。另外,這個模塊還提供了一些面向服務支持。例如:實現文件上傳的multipart請求,它也提供了Spring和其它Web框架的集成,好比Struts、WebWork。
Spring的MVC框架
Spring爲構建Web應用提供了一個功能全面的MVC框架。雖然Spring能夠很容易地與其它MVC框架集成,例如Struts,但Spring的MVC框架使用IoC對控制邏輯和業務對象提供了徹底的分離。
控制反轉(IOC),在之前開發時,對象在程序內部建立,對象的控制權屬於程序。程序應了Spring框架後,對象的建立交給Spirng框架來處理。也就是表示對象的控制權屬於Spring這個外部框架,咱們控制發生反轉。從另外一個角度來講,程序須要某對象,因爲程序自己是沒有建立對象,這個對象須要依賴外部框架來注入這個對象到程序中來。因此也叫依賴注入(DI)。
commons-logging-1.1.1.jar --不是Spring框架提供的包,日誌記錄包spring-beans-4.3.10.RELEASE.jar spring-context-4.3.10.RELEASE.jar spring-context-support-4.3.10.RELEASE.jar spring-core-4.3.10.RELEASE.jar spring-expression-4.3.10.RELEASE.jar |
<!-- 配置對象,框架運行時,自動建立這個對象,存儲在IOC容器中 --> <bean id="stu1" class="com.sgxy.entity.Student"> <property name="id" value="10001"/> <property name="age" value="20"/> <property name="name" value="張明"/> <property name="sex" value="男"/> </bean> |
//獲取IOC容器,容器的建立須要依賴配置文件,在加載配置文件時,自動建立容器中所配置的對象。 ApplicationContext cxt = new ClassPathXmlApplicationContext("config/applicationcontext.xml"); System.out.println("-------------------"); //從IOC容器中取對象 Student stu = (Student) cxt.getBean("stu1"); System.out.println(stu); |
Bean建立有3種方式,
<bean id="g1" class="com.sgxy.entity.Grade"> <property name="gradeId" value="1"/> <property name="gradeName" value="一年級"/> </bean> <!-- 配置對象,框架運行時,自動建立這個對象,存儲在IOC容器中 --> <bean id="stu1" class="com.sgxy.entity.Student"> <!-- 調用無參的構造函數建立對象,再給對象的屬性賦值 --> <property name="id" value="10001"/> <property name="age" value="20"/> <property name="name" value="張明"/> <property name="sex" value="男"/> <property name="grade"> <!-- 寫在property這個節點下面的Bean,叫內部Bean,做用域只在這個對象中。 --> <bean id="g2" class="com.sgxy.entity.Grade"> <property name="gradeId" value="2"/> <property name="gradeName" value="2年級"/> </bean> </property> </bean> <bean id="stu2" class="com.sgxy.entity.Student"> <!-- 調用帶參數的構造函數,能夠根據索引或參數名稱來進行賦值--> <constructor-arg name="id" value="10002"/> <constructor-arg name="name" value="李華"/> <constructor-arg name="sex" value="男"/> <constructor-arg name="age" value="22" /> <constructor-arg name="grade" ref="g1"/> </bean> |
工廠的建立: /** * 靜態工廠,有一個靜態方法,方法中建立對象並返回 */ public class StudentFactory { public static Student createStudent() { Grade g = new Grade(); g.setGradeId(3); g.setGradeName("三年級"); Student stu = new Student(10002,"朱小軍","男",21,g); return stu; } } |
配置文件的配置: <!-- 根據靜態工廠的方法來建立Bean對象 --> <bean id="stu3" class="com.sgxy.util.StudentFactory" factory-method="createStudent"></bean> |
實例工本實現 /** * 實例工廠,有一個方法,方法中建立對象並返回 */ public class StudentFactory { public Student createStudent() { Grade g = new Grade(); g.setGradeId(3); g.setGradeName("三年級"); Student stu = new Student(10002,"朱小軍","男",21,g); return stu; } } |
配置文件配置 <!-- 建立工廠對象 --> <bean id="studentFactory" class="com.sgxy.util.StudentFactory"/> <!-- 根據實例工廠的方法來建立Bean對象 --> <bean id="stu3" factory-bean="studentFactory" factory-method="createStudent"></bean> |
springIOC容器中的對象都默認是單例模式的。
Student stu = (Student) cxt.getBean("stu3"); System.out.println(stu.hashCode()); //從容器中又獲取一次對象 Student stu2 = (Student) cxt.getBean("stu3"); System.out.println(stu2.hashCode());
輸出結果:
|
如何配置Bean對象的做用域,scope屬性能夠修改。取值範圍:singleton(默認),prototype,request,session
singleton:單例模式
prototype:非單例模式
request,session:這兩個只能Web項目中有效,request表示一個請求,Session表示一次會話。
Beanr建立是在Spring框架加載時就建立了。有時想要須要對象時才加載對象,咱們設置對象爲延遲加載。 lazy-init="true"
<!-- 配置對象,框架運行時,自動建立這個對象,存儲在IOC容器中 --> <bean id="stu1" class="com.sgxy.entity.Student" lazy-init="true"> <!-- 調用無參的構造函數建立對象,再給對象的屬性賦值 --> <property name="id" value="10001"/> <property name="age" value="20"/> <property name="name" value="張明"/> <property name="sex" value="男"/> <property name="grade"> <!-- 寫在property這個節點下面的Bean,叫內部Bean,做用域只在這個對象中。 --> <bean id="g2" class="com.sgxy.entity.Grade"> <property name="gradeId" value="2"/> <property name="gradeName" value="2年級"/> </bean> </property> </bean>
使用效果:
|
若是想要配置文件中全部的Bean都延遲加載,則在beans節點中添加:default-lazy-init="true"
|
Bean對象的銷燬,默認是建立了Bean,這個對象一直駐紮在 IOC容器中,要等到IOC容器銷燬才釋放對象。能夠在建立Bean時設置初始化方法和銷燬的方法:
<bean id="xxx" class=「biz.OrderServiceBean" init-method="init" destroy-method="close"/>
若是一個Bean中引用另外一個Bean,則注入方式有內部Bean及ref引用外部Bean的注入。
內部Bean:
<!-- 配置對象,框架運行時,自動建立這個對象,存儲在IOC容器中 --> <bean id="stu1" class="com.sgxy.entity.Student"> <!-- 調用無參的構造函數建立對象,再給對象的屬性賦值 --> <property name="id" value="10001"/> <property name="age" value="20"/> <property name="name" value="張明"/> <property name="sex" value="男"/> <property name="grade"> <!-- 寫在property這個節點下面的Bean,叫內部Bean,做用域只在這個對象中。 --> <bean id="g2" class="com.sgxy.entity.Grade"> <property name="gradeId" value="2"/> <property name="gradeName" value="2年級"/> </bean> </property> </bean> |
ref引用外部Bean
<bean id="g1" class="com.sgxy.entity.Grade"> <property name="gradeId" value="1"/> <property name="gradeName" value="一年級"/> </bean>
<bean id="stu3" class="com.sgxy.entity.Student" destroy-method="close"> <!-- 調用帶參數的構造函數,能夠根據索引或參數名稱來進行賦值--> <constructor-arg name="id" value="10003"/> <constructor-arg name="name" value="肖月"/> <constructor-arg name="sex" value="女"/> <constructor-arg name="age" value="22" /> <property name="grade" ref="g1"/> <!-- ref引用外部Bean --> </bean> |
<property name="students"> <!-- 裝配List集合 --> <list> <bean class="com.sgxy.entity.Student" p:id="101" p:sex="男" p:name="趙一" p:age="20"></bean> <bean class="com.sgxy.entity.Student" p:id="102" p:sex="男" p:name="趙二" p:age="21"></bean> <bean class="com.sgxy.entity.Student" p:id="103" p:sex="男" p:name="趙三" p:age="22"></bean> <bean class="com.sgxy.entity.Student" p:id="104" p:sex="男" p:name="趙四" p:age="23"></bean> <bean class="com.sgxy.entity.Student" p:id="105" p:sex="男" p:name="趙四" p:age="24"></bean> </list> </property> |
<property name="students"> <!-- 裝配set集合 --> <set> <bean class="com.sgxy.entity.Student" p:id="101" p:sex="男" p:name="趙一" p:age="20"></bean> <bean class="com.sgxy.entity.Student" p:id="102" p:sex="男" p:name="趙二" p:age="21"></bean> <bean class="com.sgxy.entity.Student" p:id="103" p:sex="男" p:name="趙三" p:age="22"></bean> <bean class="com.sgxy.entity.Student" p:id="104" p:sex="男" p:name="趙四" p:age="23"></bean> <bean class="com.sgxy.entity.Student" p:id="105" p:sex="男" p:name="趙四" p:age="24"></bean> </set> </property> |
<property name="students"> <!-- 裝配map集合 --> <map> <entry key="101"> <bean class="com.sgxy.entity.Student" p:id="101" p:sex="男" p:name="趙一" p:age="20"></bean> </entry> <entry key="102"> <bean class="com.sgxy.entity.Student" p:id="102" p:sex="男" p:name="趙二" p:age="21"></bean> </entry> <entry key="103"> <bean class="com.sgxy.entity.Student" p:id="103" p:sex="男" p:name="趙三" p:age="22"></bean> </entry> </map> </property> |
@Service 建議用在Service層中的類上
@Component 若是這個類不屬於業務層,持久層,控制器層,則用這個註解,表示是一個組件。
@Controller 建議用在控制器層中的類上
@Repository 建議用在持久層中的類上
註解的方式進行配置,必須在配置文件中進行處理:
<!-- 啓用註解配置,--> <context:annotation-config/> <!-- 掃描包中的類,把有註解的類自動建立出對象,存儲在IOC容器中 --> <context:component-scan base-package="com.sgxy.service"/> |
案例:
/** * 添加以下註解,表示這個類能夠由Spring掃描到,並建立出對象 * @Service 建議用在Service層中的類上 * @Component 若是這個類不屬於業務層,持久層,控制器層,則用這個註解,表示是一個組件。 * @Controller 建議用在控制器層中的類上 * @Repository 建議用在持久層中的類上 * 這幾個註解的做用是同樣的,有4個的緣由是區別不一樣層裏面的類而已。 */ @Service public class StudentSerivce { //@Autowired //註解表示從IOC容器注入自動按類型來注入對象 @Resource(name="stu12") //這是按名稱來裝配對象 //@Autowired @Qualifier("stu1") //這兩個註解結合使用也能夠按名稱來裝配 Student student; public Student getStudent() { return student; } } |
@Autowired //註解表示從IOC容器注入自動按類型來注入對象,能夠寫在屬性前或set方法前。
@Resource(name="stu12") //這是按名稱來裝配對象
@Autowired @Qualifier("stu1") //這兩個註解結合使用也能夠按名稱來裝配。