1. Spring介紹
Spring的核心是控制反轉(IoC)和麪向切面(AoP)。
總共分爲三層結構:
- WEB層:Spring MVC
- 業務層:Bean管理(IOC)
- 持久層:Spring的JDBC模板,ORM模板用於整個其他的持久層框架
Spring 的Bean屬性注入:
1.1 Sping架構
-
核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要組件是 BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉 (IOC) 模式將應用程序的配置和依賴性規範與實際的應用程序代碼分開。
-
Spring 上下文:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能。
Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向方面的編程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何對象支持 AOP。Spring - - AOP 模塊爲基於 Spring 的應用程序中的對象提供了事務管理服務。通過使用 Spring AOP,不用依賴 EJB 組件,就可以將聲明性事務管理集成到應用程序中。 -
Spring DAO:JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不同數據庫供應商拋出的錯誤消息。異常層次結構簡化了錯誤處理,並且極大地降低了需要編寫的異常代碼數量(例如打開和關閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結構。
-
Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的對象關係工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結構。
-
Spring Web 模塊:Web 上下文模塊建立在應用程序上下文模塊之上,爲基於 Web 的應用程序提供了上下文。所以,Spring 框架支持與 Jakarta Struts 的集成。Web 模塊還簡化了處理多部分請求以及將請求參數綁定到域對象的工作。
-
Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。通過策略接口,MVC 框架變成爲高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI。
1.2 Spring配置
- 依賴包的注入
- 引入相關的配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
//引入約束
<!--將User對象交給Spring容器管理-->
<!--Bean元素;使用該元素描述需要spring容器管理的對象-->
<bean name="user" class="cn.raine.bean.User"></bean>
</beans>
1.3 Spring的工廠 (容器)
ApplicationContext
和BeanFactory
(在內存資源少的時候使用已過時)
區別:
BeanFactory :是在 getBean 的時候纔會生成類的實例.
ApplicationContext :在加載 applicationContext.xml(容器啓動)時候就會創建.
獲取容器
//創建容器對象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User u = (User) ac.getBean("user");
System.out.print(u);
1.4 Spring相關配置屬性
- id屬性:Bean 起個名字. 在約束中採用 ID 的約束:唯一. 必須以字母開始,可以使用字母、數字、連字符、 下劃線、句話、冒號 id:不能出現特殊字符.
- name屬性:Bean 起個名字. 沒有采用 ID 的約束. name:出現特殊字符.如果
<bean>
沒有 id 的話 , name 可 以當做 id 使用. - scop屬性
- singleton : 默認值,單例的
- prototype: 多例的
1.4.1 Bean的生命週期
通過配置<bean>
標籤上的init-method
作爲 Bean 的初始化的時候執行的方法,配置 destroy-method
作爲 Bean 的銷燬的時候執行的方法。 銷燬方法想要執行,需要是單例創建的 Bean 而且在工廠關閉的時候,Bean 纔會被銷燬
1. 5 Spring的注入
- Spring的bean的屬性注入
- 構造方法的注入方式
<!-- 第一種:構造方法的方式 -->
<bean id="car" class="cn.itcast.spring.demo4.Car">
<constructor-arg name="name" value=" 保時捷 "/>
<constructor-arg name="price" value="1000000"/>
</bean>
- set方法的注入屬性
<!-- 第二種:set 方法的方式 -->
<bean id="car2" class="cn.itcast.spring.demo4.Car2">
<property name="name" value=" 奇瑞 QQ"/>
<property name="price" value="40000"/>
</bean>
- 對象類型的注入
<!-- 注入對象類型的屬性 -->
<bean id="person" class="cn.itcast.spring.demo4.Person">
<property name="name" value=" 會希 "/>
<!-- ref 屬性:引用另一個 bean 的 id 或 name -->
<property name="car2" ref="car2"/>
</bean>
- 複雜類型的注入
<!--複雜類型的注入-->
<bean name="cb" class="cn.raine.injection.CollectionBean">
<property name="arr">
<list>
<value>會希</value>
<value>哈哈</value>
</list>
</property>
<property name="list">
<list>
<value>javck</value>
<value>jerry</value>
<ref bean="user2"></ref>
</list>
</property>
</bean>
構造函數注入的時候:
//確定使用哪個構造函數
<constructor-arg name="name" index="0" type="java.lang.Interger"/>
listener是spring web 包
2. AOP
2.1 使用註解配置Spring
頭部約束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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-4.2.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"
>
xml中寫入
<!--指定掃描cn.raine.bean下的所有類的註解
注意:掃描包時,會掃描指定包下所有的子包
-->
<context:component-scan base-package="cn.raine.bean"></context:component-scan>
代碼註解
//將對象注入到容器
Component("user")
Service("user") //Service層
Controller("user") //web層
@(後臺)Repository("user") //dao層
//值類型的注入
@Value("tom")
public void setNmae(String name){
...
}
//引用類型的注入
@Autowired //自定裝配
private Car car;
@Resource(name="car") //手動注入,指定注入哪個名稱的對象
private Car car;
Spring 的 Bean 管理的方式的比較
2.2 Sping接入整合Junit測試
RunWith(SpringJUnit4ClassRunner.class) //幫我們創建容器
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
@Resource(name = "user")
private User u;
@Test
public void fun1(){
}
2.3 Sping的AOP介紹
2.3.1 底層實現
代理機制
- Spring的AOP的底層用到兩種代理機制:
- JDK的動態代理:針對實現了接口的產生代理
- Cglib的到動態代理:針對沒有實現接口的類產生代理,應用的是底層的字節碼增強的技術,深層當前類的子類對象。
2.3.2 AOP的開發中的相關術語
- Joinpoint(連接點):所謂連接點是指那些被攔截到的點。在 spring 中,這些點指的是方法,因爲 spring 只 支持方法類型的連接點.
- Pointcut(切入點):所謂切入點是指我們要對哪些 Joinpoint 進行攔截的定義.
- Advice(通知/增強):所謂通知是指攔截到 Joinpoint 之後所要做的事情就是通知.通知分爲前置通知,後置 通知,異常通知,最終通知,環繞通知(切面要完成的功能)
- Introduction(引介):引介是一種特殊的通知在不修改類代碼的前提下, Introduction 可以在運行期爲類 動態地添加一些方法或 Field.
- Target(目標對象):代理的目標對象
- Weaving(織入):是指把增強應用到目標對象來創建新的代理對象的過程. spring 採用動態代理織入,而 AspectJ 採用編譯期織入和類裝在期織入
- Proxy(代理):一個類被 AOP 織入增強後,就產生一個結果代理類
- Aspect(切面): 是切入點和通知(引介)的結合
2.3.2 AOP的開發
jar包介紹
步驟
<!--準備工作:導入aop(約束)命名空間-->
<!--1.配置目標對象-->
<!--2.配置通知對象-->
<!--3.配置將通知織入目標對象-->
<!-- 配置切入點
* cn.itcast.service..*ServiceImpl.*(..)
這個service包下面的任意子包中以ServiceImpl結尾的任意類中的任意方法(任意參數) 可以返回任意類型數據
-->
前置通知 :在目標方法執行之前執行.
後置通知 :在目標方法執行之後執行
環繞通知 :在目標方法執行前和執行後執行
異常拋出通知:在目標方法執行出現 異常的時候 執行
最終通知 :無論目標方法是否出現異常 最終通知都會 執行.
目標類的創建:
//創建接口和類:
public interface OrderDao {
public void save();
public void update();
public void delete();
public void find();
}
public class OrderDaoImpl implements OrderDao {
@Override public void save() {
System.out.println("保存訂單...");
@Override public void update() {
System.out.println("修改訂單..."); }
@Override public void delete() {
System.out.println("刪除訂單..."); }
@Override public void find() {
System.out.println("查詢訂單..."); }
}
}
目標類的配置
<!-- 目標類================ -->
<bean id="orderDao" class="cn.itcast.spring.demo3.OrderDaoImpl"> </bean>
整合Jubit單元測試
引入 spring-test.jar
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo3 {
@Resource(name="orderDao")
private OrderDao orderDao;
@Test
public void demo1(){
orderDao.save();
orderDao.update();
orderDao.delete();
orderDao.find();
} }
編寫切入面
public class MyAspectXml {
// 前置增強
public void before(){
System.out.println("前置增強===========");
} }
配置完成增強
<!-- 配置切面類 -->
<bean id="myAspectXml" class="cn.itcast.spring.demo3.MyAspectXml"></bean>
<!-- 進行 aop 的配置 -->
<aop:config>
<!-- 配置切入點表達式:哪些類的哪些方法需要進行增強 -->
<aop:pointcut expression="execution(* cn.itcast.spring.demo3.OrderDao.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<aop:before method="before" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
切入點表達式:
execution(表達式)
表達式: [方法訪問修飾符] 方法返回值 包名.類名.方法名(方法的參數)
public * cn.itcast.spring.dao.*.*(..)
* cn.itcast.spring.dao.*.*(..)
* cn.itcast.spring.dao.UserDao+.*(..)
* cn.itcast.spring.dao..*.*(..)
3. Spring整合JDBC
3.1 Spring連接JDBC
導入jar包
編寫Dao文件
public class UserDaoImpl extends JdbcDaoSupport implements UserDao {
//引入了JDBCDaoSupport根據連接池創建JDBC模板,直接從父類方法中獲得就可以了
@Override
public void save(User u) {
String sql = "insert into s_user values(null, ?)";
getJdbcTemplate().update(sql, u.getName());
}
@Override
public void delete(Integer id) {
String sql = "delete from s_user where id =?";
getJdbcTemplate().update(sql, id);
}
@Override
public void update(User u) {
String sql = "update s_user set name = ? where id = ?";
getJdbcTemplate().update(sql, u.getName(), u.getId());
}
//查詢單個對象
@Override
public User getById(Integer id) {
String sql = "select * from s_user where id = ?";
return getJdbcTemplate().queryForObject(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int i) throws SQLException {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
return u;
}
});
}
//查詢值類型
@Override
public int getTotalCount() {
String sql = "select count(*) from t_user ";
Integer count = super.getJdbcTemplate().queryForObject(sql, Integer.class);
return count;
}
//查詢list集合類型
@Override
public List<User> getAll() {
String sql = "select * from s_user";
List<User> list = getJdbcTemplate().query(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int i) throws SQLException {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
return u;
}
});
return list;
}
}
Spring配置
<!--指定spring讀取db.properties配置-->
<context:property-placeholder location="classpath:db.properties"/>
<!--指定spring讀取db.properties配置-->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--將JDBCTemplate放入spring容器-->
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 3.將UserDao放入spring容器 -->
<bean name="userDao" class="cn.raine.jsbctemplate.UserDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
3.2 事務
3.2.1 事務特性
- 原子性 :強調事務的不可分割.
- 一致性 :事務的執行的前後數據的完整性保持一致.
- 隔離性 :一個事務執行的過程中,不應該受到其他事務的干擾
- 持久性 :事務一旦結束,數據就持久到數據庫
3.2.2設置事務隔離級別
- 未提交讀 :髒讀,不可重複讀,虛讀都有可能發生
- 已提交讀 :避免髒讀。但是不可重複讀和虛讀有可能發生
- 可重複讀 :避免髒讀和不可重複讀.但是虛讀有可能發生.
- 串行化的 :避免以上所有讀問題.
####3.2.3 真正管理事務的對象
***** 真正管理事務的對象
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用 Spring JDBC 或 iBatis 進行持久化數據時使用
org.springframework.orm.hibernate3.HibernateTransactionManager 使用 Hibernate 版本進行持久化數據時使用
3.2.4 事務的傳播行爲
PROPAGION_XXX :事務的傳播行爲
-
保證同一個事務中
PROPAGATION_REQUIRED 支持當前事務,如果不存在 就新建一個(默認) PROPAGATION_SUPPORTS 支持當前事務,如果不存在,就不使用事務
PROPAGATION_MANDATORY 支持當前事務,如果不存在,拋出異常 -
保證沒有在同一個事務中
PROPAGATION_REQUIRES_NEW 如果有事務存在,掛起當前事務,創建一個新的事務
PROPAGATION_NOT_SUPPORTED 以非事務方式運行,如果有事務存在,掛起當前事務
PROPAGATION_NEVER 以非事務方式運行,如果有事務存在,拋出異常
PROPAGATION_NESTED 如果當前事務存在,則嵌套事務執行
3.2.5 Spring管理事務方式
3.2.5.1 xml配置
xml配置
<!--事務核心管理器,封裝了所欲事務操作,依賴於連接池-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事務模板對象-->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<!--配置事務通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 以方法爲單位,指定方法應用什麼事務屬性
isolation:隔離級別
propagation:傳播行爲
read-only:是否只讀-->
<tx:method name="save" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
<!--配置織入-->
<aop:config>
<!--配置切點表達式-->
<aop:pointcut id="txPc" expression="execution(* cn.raine.service.*ServiceImpl.*(..))" />
<!-- 配置切面 : 通知+切點
advice-ref:通知的名稱
pointcut-ref:切點的名稱
-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
<bean name="accountDao" class="cn.raine.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean name="accountService" class="cn.raine.service.AccountServiceImpl">
<property name="ad" ref="accountDao"></property>
<property name="tt" ref="transactionTemplate"></property>
</bean>
在Service中調用模板
public void transfer(Integer from, Integer to, Double money) {
tt.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//減錢
ad.decreaseMoney(from, money);
//加錢
ad.increaseMoney(to, money);
}
});
3.2.5.2 註解配置
開啓註解管理事務
<!--開啓使用註解管理aop事務-->
<tx:annotation-driven/>
使用註解
@Override
@Transactional(isolation = ![這裏寫圖片描述](http://img.blog.csdn.net/20171210101028916?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTGVicm9uX3hpYQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void transfer(Integer from, Integer to, Double money) {
//減錢
ad.decreaseMoney(from, money);
// int i = 1/0;
//加錢
ad.increaseMoney(to, money);
}