Java工程師培訓課(十八【新的領域】)
夜光序言:
正文:
框架概述:
Struts2: 基於mvc模式的應用層框架!
主要是作為控制層元件,javabean, jsp!
Hibernate: 持久層元件,簡化jdbc操作!
Spring: 主要有六大模組功能
事務管理!
與其他框架整合!
Mvc開發模式:
基於mvc模式的專案分層!
1. Spring框架
Spring , 春天來了!
- 框架理解
框架,都會預先實現一些功能,給開發人員開發提供便利!
提高開發效率、提升程式可擴充套件性、健壯!
- 專業術語
高內聚、低耦合:
類內部的關係越緊密越好,類與類的關係越少越好!
非侵入式設計:
侵入式設計:
引入的元件對現有的類的結構會有影響,這種就是“侵入式設計”的元件!
Struts2: 侵入式設計!
Hibernate: 非侵入式設計!
非侵入式設計:
引入元件對現有的類的結構沒有影響!
Spring, 非侵入式設計
IOC 容器
Inversion of control 控制反轉
控制反轉容器! -à 物件建立的問題!
解釋:
User user = new User(); 自己控制物件的建立
現在需要物件,自己不建立,交給外部的容器建立,叫控制反轉!
IOC容器= bean.xml配置 + ApplicationContext容器類
DI, dependency injection 依賴注入
建立物件後,處理物件的依賴關係!
User user = new User();
user.setAddress(..) ;// 需要DI(依賴注入)
Aop…
- Spring框架
Spring 開源框架,提供的是一站式解決方案!
六大模組:
…..
- Spring 第一個案例, 解決專案中如何建立物件
1) 引入jar檔案 (3.2版本)
commons-logging-1.1.3.jar 【單獨下載】
spring-beans-3.2.5.RELEASE.jar 【spring原始碼, bean節點管理】
spring-context-3.2.5.RELEASE.jar 【spring上下文類】
spring-core-3.2.5.RELEASE.jar 【IOC容器】
spring-expression-3.2.5.RELEASE.jar 【spring表示式】
注意:
使用的版本Spring3.2
在這個版本中,只有spring自身的核心功能,spring依賴的其他元件,需要單獨下載! 例如:日誌jar檔案,就需要單獨下載!
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: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">
</beans> |
3) 配置
<!-- 建立Dao例項 --> <bean id="userDao" class="cn.itcast.dao.UserDao"></bean>
<!-- 建立Service例項 --> <bean id="userService" class="cn.itcast.service.UserService"> <property name="userDao" ref="userDao"></property> </bean>
<!-- 建立Action例項 --> <bean id="userAction" class="cn.itcast.action.UserAction"> <property name="userService" ref="userService"></property> </bean> |
4) 測試
// 從IOC容器獲取物件 @Test public void testApp2() throws Exception { // 容器物件(載入applicationContext.xml配置檔案) ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); // 獲取物件 UserAction userAction = (UserAction) ac.getBean("userAction"); userAction.execute(); } |
2. Spring IOC 容器
建立bean細節:
1) bean在容器中的寫法
2) bean宣告週期
<?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: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">
<!-- 把物件加入IOC容器 -->
<!-- 細節1: id 與 name: id 不能以數字開頭,不能含有特殊符號, 不能有空格、逗號等; id 不能重複! name 可以以數字開頭,可以有特殊符合,如果name值重複,編譯沒有問題但執行報錯!
<bean id="user" name="user2,user3 user4" class="cn.itcast.a_config.User"></bean> <bean name="user5" class="cn.itcast.a_config.User"></bean> <bean id="user6" class="cn.itcast.a_config.User"></bean> <bean id="user6" class="cn.itcast.a_config.User"></bean> -->
<!-- 細節2: (單例/多例) --> <!-- scope="singleton" 預設表示單例! prototype 多例 init-method="" 在建立完物件之後執行初始化方法 destroy-method="" 在呼叫容器類的destroy()方法時候,對單例的物件有效! lazy-init="true" 延遲初始化 / 這個屬性的設定只對單例有影響,對多例沒有任何影響! 單例的物件預設是在建立容器的時候就建立所有單例的物件,如果希望在第一次訪問的時候建立單例的物件,就設定延遲初始化 Bean生命週期: bean在xml中配置, singleton 單例 1) 建立物件 如果有配置延遲初始化, lazy-init=true 如果單例的物件有配置延遲初始化, 在建立容器之後,在第一次從容器獲取物件的時候 建立單例的物件! 如果沒有配置或延遲初始化為預設值, 單例的物件會在建立容器的時候建立物件 2) 執行初始化方法 , init-method配置的方法會執行 3) 呼叫容器destroy() 方法時候,容器在銷燬單例物件的例項的時候,會呼叫destroy-method對應的方法 此時bean物件會被銷燬!
prototype 多例 1) 每次在從容器獲取物件的時候,都會建立新的物件 2) 每次建立完物件後,就執行初始化方法 3) java回回收不用資源(jvm gc) --> <bean id="user" class="cn.itcast.a_config.User" init-method="init" destroy-method="destroy_" lazy-init="false" scope="prototype"></bean>
</beans> |
建立物件的幾種方式
建立物件的幾種方式:
1) 呼叫無引數構造器
2) 呼叫有引數構造器
3) 工廠
* 靜態方法
<bean id=”’ class=”” factory-method=””/>
* 非靜態方法
<bean id=”factory” class=”..”>
<bean id=”” factory-bean=” factory” factory-method=”例項方法” />
4) 反射
|
處理物件的依賴關係
給物件屬性賦值(DI, 依賴注入),幾種方式:
1) 建構函式賦值
2) set 方法注入值
* 普通欄位賦值
* 集合屬性 (list/map/property)
3) 案例
Dao/service/action例項,處理依賴關係
* 常用的通過set方法注入
* 內部bean
* p 名稱空間
* 自動裝配
* 註解
註解總結:
@Component 表示一個元件(類),把當前元件加入ioc容器
加入容器的元件的名稱預設是類名第一個字母小寫
@Component(“”) 指定加入ioc容器的元件類的類名
@Repository 標識是一個持久層的元件
@Service 標識是一個業務邏輯層的元件
@Controller 標識是一個控制層的元件
@Scope("prototype") 指定物件單例/多例
@Resource 1. 預設根據修飾的欄位名稱會取ioc容器找物件自動注入
找到後注入
2. 如果名稱沒有找到,再根據型別查詢 找到後就立刻注入
如果改型別在ioc容器中有多個物件,報錯!
3. 根據型別也沒有找到物件,報錯!
@Resource(name =””) 會根據指定的名稱去容器找物件自動注入
配置方式與註解方式:
1. 配置, 便於維護
(配置過多,比較繁瑣)
2. 註解, 開發方便
(簡化配置,不利於後期維護,如果修改物件建立、關係處理,需要改程式碼!)
3. Spring 與Struts整合
Spring與struts整合,關鍵點:
把action的建立,交給spring的ioc容器!
所以,需要引入jar檔案:
struts2-spring-plugin-2.3.4.1.jar 【struts原始碼】
spring-web-3.2.5.RELEASE.jar 【spring原始碼】
整合完整步驟:
1. 引入jar
Struts核心jar
Spring
Core 核心 (5個)
Web 對web支援 (2個)
2. 配置
bean.xml
struts.xml
web.xml
struts2核心過濾器
啟動時候,配置載入springIOC容器
3. Action 類
夜光任務:
1. 寫簡單案例,練習spring 、
* 搭建spring環境
* 測試OK
* dao/service/action
然後處理物件依賴關係,
* set方法注入值, 幾種方式
* 註解
2. spring與struts整合,小案例
3. 優化前面專案,
融入spring功能!
目標:
1.代理模式
2. Aop程式設計
* 手動實現aop程式設計
* spring Aop 註解方式
* Spring Aop XML 配置
* 切入點表示式語法詳解
3. Spring 對jdbc模組的支援
1. 代理模式
概念
Proxy, 表示代理! 提供了對目標物件另外的訪問方式,即通過代理訪問目標物件!
Java中代理:
靜態代理
動態代理
Jdk 代理
Cglib 代理
Spring預設支援
靜態代理
特點:
1. 目標物件必須要實現介面
2. 代理物件,要實現與目標物件一樣的介面
需求:
IUserDao.java dao介面
UserDao.java dao實現
Void save(); // 儲存實現
UserDaoProxy.java dao代理類,對UserDao中功能進行擴充套件!
App
缺點:
1. 代理物件,需要依賴目標物件的介面!
如果介面功能變化,目標物件變化,會引入代理物件的變化!
2. 對每一個目標物件,都要分別寫一個代理類,麻煩!
(代理工廠)
動態代理
動態代理:
1. 通常說的動態代理,就是指jdk代理!
因為是通過jdk的api在執行時期,動態的生成代理物件的!
2. 目標物件一定要實現介面, 代理物件不用實現介面!
JDK 生成代理物件的Api
|-- Proxy
static Object |
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) |
引數loader :
當前目標物件使用的類載入器!
引數interfaces :
當前目標物件實現的介面
引數 h:
介面型別,事件處理器.
當執行目標物件方法的時候,會觸發事件; 把當前執行的方法(method物件),傳入事件處理器方法引數中, 這樣就可以根據業務邏輯,判斷是否執行目標物件方法或擴充套件功能!
Cglib代理
也叫”子類代理”
當目標物件沒有實現介面,就不能使用jdk提供的代理,可以以子類的方式實現!
在執行時期動態在記憶體中構建一個子類物件的方法,從而對目標物件擴充套件,這種就是cglib代理!
Spring也支援cglib代理,核心包中已經包含此功能!
- JDK的動態代理有一個限制,就是使用動態代理的物件必須實現一個或多個介面。如果想代理沒有實現介面的類,就可以使用CGLIB實現。
- CGLIB是一個強大的高效能的程式碼生成包,它可以在執行期擴充套件Java類與實現Java介面。它廣泛的被許多AOP的框架使用,例如Spring AOP和dynaop,為他們提供方法的interception(攔截)。
- CGLIB包的底層是通過使用一個小而快的位元組碼處理框架ASM,來轉換位元組碼並生成新的類。不鼓勵直接使用ASM,因為它要求你必須對JVM內部結構包括class檔案的格式和指令集都很熟悉。
如:
public class UserDao { }
public class $Cglib_my_class extends UserDao {}
總結:
1. 目標物件可以不實現介面
2. 目標類不能為final, 如果為final報錯
3. 方法如果為final/static, 不會被代理攔截! 會直接執行目標物件方法 !
代理總結
在SpringAop程式設計中,
如果目標物件有實現介面,spring使用jdk提供的代理生成代理物件!
如果目標物件沒有實現介面,使用cglib代理!
如果目標沒有實現介面、且為final , 不能進行aop程式設計,報錯!不能生成代理!
2. Aop程式設計
public void add(User user) { Session session = null; Transaction trans = null; try { session = HibernateSessionFactoryUtils.getSession(); 【關注點程式碼】 trans = session.beginTransaction(); 【關注點程式碼】
session.save(user); // 業務
trans.commit(); 【關注點程式碼】 } catch (Exception e) { e.printStackTrace(); if(trans != null){ trans.rollback(); } } finally{ HibernateSessionFactoryUtils.closeSession(session); } }
|
Aop 程式設計,
主要是分離業務程式碼與關注點程式碼!
關注點程式碼,寫一次,在執行業務程式碼時候動態植入關注點程式碼!
自己實現aop程式設計
aop程式設計, 註解方式
概念:
Aop程式設計:
關注點程式碼與業務程式碼分離!(jdk/cglib代理)
關注點:
重複執行的程式碼, 也叫關注點程式碼!
切面:
關注點程式碼形成的類,就叫做切面
springAop程式設計,也叫面向切面程式設計!
Aop: Aspect Object Programming 面向切面程式設計!
舉例,哪些是切面?
事務,許可權控制, 日誌…
切入點表示式
攔截方法,給方法所在的類,生成代理物件!
Spring在初始化容器的時候,會根據切入點表示式的規則,會符合攔截規則的方法所在的類生成代理物件!
使用Aop開發步驟:
1. 引入aop 相關 jar檔案
(aspectj 在spring之前,面向切面開發的公用元件)
aopalliance.jar 【spring-framework-2.5.6\lib\aopalliance】
aspectjrt.jar 【spring-framework-2.5.6\lib\aspectj】
aspectjweaver.jar 【spring-framework-2.5.6\lib\aspectj】
spring-aop-3.2.5.RELEASE.jar 【Spring3.2原始碼】
2. 引入aop名稱空間
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" 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">
<!-- 開啟註解掃描 --> <context:component-scan base-package="cn.itcast.e_aop_anno"></context:component-scan> <!-- 開啟aop註解 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans> |
3. 開啟aop註解
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
4. 使用Aop相關注解
@Aspect 指定一個類為切面類
(切面類也需要例項化)
(切面類中的方法,也叫做通知)
@Before 前置通知 【在執行目標物件方法之前執行】
@After 後置通知 【在執行目標物件方法之後執行】
@AfterReturning 返回後通知 【在執行目標物件方法結束後執行, 出現異常不執行】
@AfterThrowing 異常通知 【在執行目標物件方法出現異常時候執行】
@Around 環繞通知 【環繞目標方法執行】
@Pointcut 定義一個切入點表示式變數 (後面使用這個切入點表示式的時候,直接引用方法名即可)
Spring生成代理物件的過程?
1. 建立容器物件的時候, 根據“切入點表示式”攔截的類,生成代理物件;
2. 如果目標物件有實現介面,使用jdk代理!
3. 如果目標物件沒有實現介面,使用cglib代理!
4. 從容器獲取代理後的物件
5. 執行代理物件的方法,在執行時期,動態植入“切面”類中的“通知”!
aop程式設計, XML配置方式
步驟:
1. 引入aop 相關jar檔案
2. bean.xml 引入aop名稱空間
3. 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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" 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">
<!-- dao例項加入容器 --> <bean id="userDao" class="cn.itcast.f_aop_xml.UserDao"></bean>
<!-- 例項化切面類 --> <bean id="aop" class="cn.itcast.f_aop_xml.TransactionAop"></bean>
<!-- Aop相關配置 --> <aop:config> <!-- 切入點表示式定義 --> <aop:pointcut expression="execution(* cn.itcast.f_aop_xml.UserDao.*(..))" id="pt"/>
<!-- 切面配置 --> <aop:aspect ref="aop">
<!-- 【環繞通知】 --> <aop:around method="arroud" pointcut-ref="pt"/>
<!-- 【前置通知】 在目標方法之前執行 --> <aop:before method="beginTransaction" pointcut-ref="pt" />
<!-- 【後置通知】 --> <aop:after method="commit" pointcut-ref="pt"/>
<!-- 【返回後通知】 --> <aop:after-returning method="afterReturing" pointcut-ref="pt"/>
<!-- 異常通知 --> <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
</aop:aspect> </aop:config>
</beans>
|
切入點表示式語法詳解
切入點表示式:
攔截指定的類,生成代理物件!
execution(
modifiers-pattern? 攔截的方法的訪問修飾符
ret-type-pattern 方法返回型別,必須指定
declaring-type-pattern? 攔截的方法所在的類
name-pattern(param-pattern) 攔截的方法(以及方法的引數列表)
throws-pattern?) 方法宣告的異常
總結:
攔截,一定要指定到方法!
共性問題:
1. @Override報錯
Jdk1.5 只支援父類方法的重寫,不支援介面
Jdk1.6 修復這個問題
修改編譯編譯,改為1.6
2. xml配置沒有提示
3. Spring 對jdbc模組的支援
學習了Spring的功能有:
Spring Core ioc容器
Spring Web 對web支援(與struts整合)
Spring Aop 面向切面程式設計
Spring Jdbc 對jdbc的支援
Spring 物件Jdbc的支援,
Spring 對jdbc的操作進行了簡化!
提供了JdbcTemplate模板工具類,簡化jdbc的操作!
如果想用spring jdbc功能,先引入jar檔案:
spring-jdbc-3.2.5.RELEASE.jar 工具類包
spring-tx-3.2.5.RELEASE.jar 事務支援依賴包
連線池、資料庫驅動包!
開發步驟:
1. 原始的jdbc操作程式碼
2. 對連線管理
3. 對jdbc操作進行簡化
à JdbcTemplate 工具類Api
à JdbcTemplate與DataSource依賴關係
重點:
1. Aop, xml配置方式實現
2. Aop, 註解方式實現
-----------------------
3. 三種代理模式,練習
4. Spring 對jdbc支援
目標:
1. Spring宣告式事務管理
2. Spring 與 Hibernate 整合
* Spring建立SessionFactory幾種方式
* Spring對dao操作的支援
3. SSH 初步整合
1. Spring宣告式事務管理
概念
- 事務是一組操作的執行單元,相對於資料庫操作來講,事務管理的是一組SQL指令,比如增加,修改,刪除等,事務的一致性,要求,這個事務內的操作必須全部執行成功,如果在此過程種出現了差錯,比如有一條SQL語句沒有執行成功,那麼這一組操作都將全部回滾
- 事務特性(ACID)
- Atomic(原子性):要麼都成功,要麼都失敗
- Consistent(一致性):資料應該不被破壞
- Isolate(隔離性):使用者間操作不相混淆
- Durable(永續性):永久儲存
程式中兩種事務管理方式
- 程式設計式事務管理
- 編寫程式式的事務管理可以清楚的定義事務的邊界,可以實現細粒度的事務控制,比如你可以通過程式程式碼來控制你的事務何時開始,何時結束等,與後面介紹的宣告式事務管理相比,它可以實現細粒度的事務控制,例如jdbc,hibernate,spring中不提倡使用。
JDBC事務控制:
con.setAutoCommite (false); 設定事務手動提交
Hibernate中事務控制:
session.beginTransaction(); 開啟事務
優缺點:
1. 事務控制精確
2. 事務程式碼,與業務邏輯處理程式碼,耦合在一起!
事務程式碼,不能共用! 重新寫事務控制操作!
開發效率低,不便於維護! (不想用事務,要改程式碼!)
- 宣告式事務管理 (在Spring中使用)
- 如果你並不需要細粒度的事務控制,你可以使用宣告式事務,在Spring中,你只需要在Spring配置檔案中做一些配置,即可將操作納入到事務管理中,解除了和程式碼的耦合, 這是對應用程式碼影響最小的選擇,從這一點再次驗證了Spring關於AOP的概念。當你不需要事務管理的時候,可以直接從Spring配置檔案中移除該設定
特點:
1. Spring提供的宣告式事務管理,用到Aop概念!
2. 對指定的方法新增事務控制,這裡只需要配置即可!
3. 修改事務控制實現或刪除事務控制操作,只需要移除xml事務相關配置!
注意:
只能對某個方法應用事務! (因為“切入點表示式”攔截的是方法,控制不了方法內部程式碼!)
所以,Spring宣告式事務管理,即為粗粒度的事務控制!
宣告式事務管理器類:
Jdbc:
DataSourceTransactionManager 管理jdbc中事務控制
Hibernate:
HibenateTransactionManager 管理hibernate中事務控制
宣告式事務管理 – JDBC
|
XML 配置方式實現
事務控制在Service層:
步驟:
1. 引入jar檔案
Spring 核心
Spring Aop 切面程式設計
Spring-jdbc / Spring-tx / 驅動包、連線池
2. dao/service
3. 配置
* 資料來源
* JdbcTemplate
* Dao/Service
* spring宣告式事務管理配置
(攔截service方法的執行,動態植入事務控制程式碼!)
4. 測試
Save();
Int i = 1/0;
Save();
<?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. 資料來源配置 --> <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"< |