Spring framework簡介
spring framework這個框架是spring項目中的核心項目,所有框架都依賴於這個框架.
它是一個一站式的開源框架,基礎技術是IoC.
按官方文檔主要分塊為核心技術,測試,數據訪問,Web,Integration
核心技術主要表現在Ioc容器,資源訪問類Resource,校驗,數據綁定和類型轉換,Spring EL表達式,AOP
測試包含單元測試以及Integration測試
數據訪問包含事務管理, DAO support, JDBC支持, ORM支持(Mybatis,Hibernate)
Web包含Spring MVC,WebSocket支持,其他MVC框架支持(Struts)
Integration是分布式項目會使用到的功能,不了解.
上圖的每一個模塊都對應了相當的jar包,所以使用某一模塊必須把jar包依賴導入,
IoC概念以及目標
IoC就是讓原本你自己管理的對象交由容器來進行管理,其主要的目的是松耦合.
IoC發展史
既然IoC的目標是為了松耦合,那它怎么做到的?
最后目標:降低對象之間的耦合度,IoC技術加入了配置把編碼中對象的耦合度降低了.
IoC的底層原理
IoC底層使用的技術包括:
(1)xml配置文件
(2)dom4j解決xml
(3)工廠設計模式
(4)反射
IoC應用入門
一.導入jar包
IoC是Spring framework的基礎技術,所以需要導入基礎包;
二.創建類,在類里面創建方法
需要創建交與容器的類模板(擁有getter和setter的POJO類)
三.創建spring配置文件,配置創建類
(1)spring的核心配置文件名稱和位置不是固定的,
官方推薦放置於src下面,命名為applicationContext.xml
(2)引入schema約束
(3)配置對象創建
四.測試對象創建
xml配置文件頭部提示錯誤
解決方法是把schema約束引入spring,把約束文件引入到spring中.
IoC的三種配置管理方式
xml配置
實例化的三種方式
第一種使用類無參構造(重點)
第二種使用靜態工廠來進行實例化
第三種使用實例工廠創建
bean標簽常用的屬性
常用屬性有id, class, name, scope
id用於創建標識
class鍵入類的全路徑名,引入模板類
name和id功能一致,但name允許包含特殊字符
scope用於指定創建類的方式以及其使用范圍,參數如下
-singleton 單例創建對象,也就是始終都復用同一個對象,不會進行第二輪的創建
-prototype 每次創建都會創建一個新的對象
-request 創建對象並放置到request域中
-session 創建對象並放置到session域中
-globalSession 用於實現單點登錄功能,比如百度下有百度雲,百度翻譯,百度相冊之類多個應用,但是你只要登錄上一個位置,多個位置都可以使用登錄信息,這就是單點登錄;這個參數基本不會使用,因為有一種就redis的技術更好地實現了這種功能.
屬性注入
屬性注入三種方式
set方法注入屬性,其中包含基礎屬性注入,對象屬性注入,復合屬性注入
基礎屬性注入
對象屬性注入
復合屬性的注入
1.數組
2.list集合
3.map集合
4.properties

<bean id="person" class="com.harry.ioc.test"> <!-- 數組 --> <property name="arrs"> <list> <value>引用名1</value> <value>引用名2</value> <value>引用名3</value> </list> </property> <!-- list --> <property name="list"> <list> <value>引用名4</value> <value>引用名5</value> <value>引用名6</value> </list> </property> <!-- map --> <property name="map"> <map> <entry key="aa" value="引用名7"></entry> <entry key="bb" value="引用名8"></entry> <entry key="cc" value="引用名9"></entry> </map> </property> <!-- properties --> <property name="properties"> <props> <prop key="driverclass">com.mysql.jdbc.Driver</prop> <prop key="username">root</prop> </props> </property> </bean>
有參構造函數注入屬性
javaConfig類(有待補充)
注解
一.注解介紹
1.代碼里特殊標記,使用注解可以完成功能
2.注解寫法 @(屬性名稱=屬性值)
3.注解可以使用在類,方法和屬性之上
二.spring的注解開發導入包
1.core包
2.aop包
三.創建類和方法
四.創建spring配置文件引入新約束,開啟注解掃描
五.注解創建對象
1.使用注解標記類
2.創建對象有四個注解標記
3.創建對象方式,單例還是多例
六.注解注入屬性
1.創建service類,創建dao類
2.在service類使用注解注入dao
方式一.采用自動裝載@Autowired
方式二.采用@Resource獲取特定名稱對象
七.配置文件和注解混合使用
1.配置文件創建對象注入容器
2.使用注解讓容器實現屬性注入
IoC和DI的區別所在
很多人認為IoC和DI是一個事物的兩種說法,其實之間存在着細微的不同.
-IoC,控制反轉,將對象交由容器進行管理;
-DI,依賴注入,將屬性注入於對象之中;
-DI是依賴於控制反轉技術的,如果使用IoC技術也就無法使用注入功能.
Spring整合web項目的原理
1 加載spring核心配置文件,
2 實現思想:把加載配置文件和創建對象過程,在服務器啟動時候完成
3 實現原理
(1)ServletContext對象
(2)監聽器
(3)具體使用:
- 在服務器啟動時候,為每個項目創建一個ServletContext對象
- 在ServletContext對象創建時候,使用監聽器可以具體到ServletContext對象在什么時候創建
- 使用監聽器監聽到ServletContext對象創建時候,
-- 加載spring配置文件,把配置文件配置對象創建
-- 把創建出來的對象放到ServletContext域對象里面(setAttribute方法)
- 獲取對象時候,到ServletContext域得到 (getAttribute方法)
AOP基礎概念
線程中的方法棧
java程序虛擬機啟動時會載入程序碼,虛擬機會為每一條正在運行的線程生成一個方法調用棧,線程以方法運行為執行單位.
AOP概念以及目標
AOP是面向切面編程,其實就是在不修改代碼模塊的情況下在你的模塊中嵌入一些其他的代碼.
目標是統一模塊,從而抽取並消除一些散落在系統中塊狀代碼(非業務邏輯).
AOP術語圖解
連接點:就是所有線程的方法,可以作為嵌入代碼的候選對象;
切入點:最后被選為嵌入代碼的對象;
切面:實現嵌入的對象;
增強通知:嵌入的內容(一些被定義的方法,包括前置通知,后置通知,異常通知,最終通知,環繞通知)
織入:嵌入代碼的整個過程被叫做織入
AOP原理
AOP的出現是有了在業務代碼中嵌入一些非業務代碼,如日志通知,如連接數據庫等事務.
1.修改源代碼,過度耦合無關業務的代碼;
2.無論是使用繼承方式還是接口實現方式添加無關業務的代碼,都會使對象間過度耦合;
3.使用動態代理模式來實現AOP,讓容器去幫我們進行代碼嵌入.
AOP使用解析(xml)
1.導入jar包(包括core包和aop包)
Spring的AOP是基於aspectj框架的,所以在導包時需要導入aspectj的支持包
2.創建spring核心配置文件,導入aop約束
3.配置bean對象,注入至容器中,並配置切面與切點
注:常用的表達式
execution(<訪問修飾符>?<返回類型><方法名>(<參數>)<異常>)
(1)execution(* com.harry.aop.service.UserService.add(..))
(2)execution(* com.harry.aop.service.UserServic.*(..))
(3)execution(* *.*(..))
(4) 匹配所有save開頭的方法 execution(* save*(..))
AOP使用解析(注解)
1.開啟aop功能掃描
2.創建bean來作為切面類和切點類
3.創建切面切點定義
事務控制
事務是什么?事務控制?
事務這個詞最早是在數據庫中進行應用,講的用戶定義的一個數據庫操作序列,這些操作要么全做要么全不做,是一個不可分割的工作單位。
事務的管理是指一個事務的開啟,內容添加,提交和回滾.
代碼層次的事務控制
事務控制原本是在數據庫進行的,但由於ORM映射后,操作數據庫的語句未必是SQL語句,事務控制也被遷移到了工程語言上(Java/C++/Python).Spring framework支持了事務管理的機制,通過ORM映射后可以在業務代碼中實現事務控制.
事務控制形式
編程式事務控制
自己手動控制事務,jdbc和Hibernate提供這種事務管理方式.
conn.setAutoCommit(false); //jdbc設置手動控制事務
session.beginTransaction(); //Hibernate開始一個事務
這種方式可以控制到代碼細節,靈活多變.
聲明式事務控制
以方法為單位,可以在類的方法中織入事務控制的代碼,從而解除了事務代碼與業務代碼的耦合.
這種方式需要在配置文件中配置,雖然無法控制到代碼細節(無法在某個方法中的某幾行加入事務控制),但一般情況適用.
Spring事務控制
利用AOP技術實現聲明式事務控制,包括XML方式和注解方式.
xml方式
1.導入jar包
2.加入ioc,aop,apectj,tx等約束,並配置數據源,聲明式事務,aop

<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 1. 數據源對象: C3P0連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> <property name="initialPoolSize" value="3"></property> <property name="maxPoolSize" value="10"></property> <property name="maxStatements" value="100"></property> <property name="acquireIncrement" value="2"></property> </bean> <!-- 2. JdbcTemplate工具類實例 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 3. dao實例 --> <bean id="deptDao" class="com.harry.transaction.dao.DeptDao"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!-- 4. service實例 --> <bean id="deptService" class="com.harry.transaction.service.DeptService"> <property name="deptDao" ref="deptDao"></property> </bean> <!-- #############5. Spring聲明式事務管理配置############### --> <!-- 5.1 配置事務管理器類 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 5.2 配置事務增強(如果管理事務?) --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="*" read-only="false"/> </tx:attributes> </tx:advice> <!-- 5.3 Aop配置: 攔截哪些方法(切入點表表達式) + 應用上面的事務增強配置 --> <aop:config> <aop:pointcut expression="execution(* ccm.harry.transaction.service.save*(..))" id="pt"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/> </aop:config> </beans>
注解方式
1.導入jar包
2.xml數據源配置,事務管理類配置,開啟ioc,aop,事務注解掃描.

<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 1. 數據源對象: C3P0連接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> <property name="initialPoolSize" value="3"></property> <property name="maxPoolSize" value="10"></property> <property name="maxStatements" value="100"></property> <property name="acquireIncrement" value="2"></property> </bean> <!-- 2. JdbcTemplate工具類實例 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 事務管理器類 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 開啟注解掃描 --> <context:component-scan base-package="com.harry.transaction"></context:component-scan> <!-- 注解方式實現事務: 指定注解方式實現事務 --> <tx:annotation-driven transaction-manager="txManager"/> </beans>
3.在Dao中的類或者類方法上使用@Transactional來表明事務增強的切入點
事務屬性

@Transactional( readOnly = false, // 讀寫事務 timeout = -1, // 事務的超時時間不限制 noRollbackFor = ArithmeticException.class, // 遇到數學異常不回滾 isolation = Isolation.DEFAULT, // 事務的隔離級別,數據庫的默認 propagation = Propagation.REQUIRED // 事務的傳播行為 ) public void save(Dept dept){ deptDao.save(dept); int i = 1/0; deptDao.save(dept); }
上述屬性除了事務傳播行為,其他都容易理解.重點需要理解事務的傳播行為.
Propagation.REQUIRED
指定當前的方法必須在事務的環境下執行;
如果當前運行的方法,已經存在事務, 就會加入當前的事務;
Propagation.REQUIRED_NEW
指定當前的方法必須在事務的環境下執行;
如果當前運行的方法,已經存在事務: 事務會掛起; 會始終開啟一個新的事務,執行完后; 剛才掛起的事務才繼續運行。

/***************************回滾,日志不會寫入************************/ Class Log1{ Propagation.REQUIRED insertLog(); } Propagation.REQUIRED Void saveDept(){ insertLog(); // 加入當前事務 .. 異常, 會回滾 saveDept(); } /****************回滾,日志會開啟新事務並進行寫入****************/ Class Log2{ Propagation.REQUIRED_NEW insertLog(); } Propagation.REQUIRED Void saveDept(){ insertLog(); // 始終開啟事務 .. 異常, 日志不會回滾 saveDept(); }