1. 程式人生 > >Java工程師培訓課(十八【新的領域】)

Java工程師培訓課(十八【新的領域】)

夜光序言:

 

不亂於心,   不困於情.    不畏將來,     不念過往.如此,安好~
深謀若谷,   深交若水.    深明大義,     深悉小節.已然,靜舒~
善寬以懷,   善感以恩.    善博以浪,     善精以業.這般,最佳~
勿感於時,   勿傷於懷.    勿耽美色,     勿沉虛妄.從今,進取~ 
無愧於天,   無愧於地.    無怍於人,     無懼於鬼.這樣,人生

~

 

正文:

框架概述:

Struts2:  基於mvc模式的應用層框架!

主要是作為控制層元件,javabean, jsp!

Hibernate: 持久層元件,簡化jdbc操作!

Spring:   主要有六大模組功能

 事務管理!

 與其他框架整合!

 

Mvc開發模式:

基於mvc模式的專案分層!

 

 

1. Spring框架

Spring ,  春天來了!

 

  1. 框架理解

框架,都會預先實現一些功能,給開發人員開發提供便利!

  提高開發效率、提升程式可擴充套件性、健壯!

  1. 專業術語

高內聚、低耦合:

類內部的關係越緊密越好,類與類的關係越少越好!

非侵入式設計:

侵入式設計:

引入的元件對現有的類的結構會有影響,這種就是“侵入式設計”的元件!

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…

 

  1. Spring框架

Spring 開源框架,提供的是一站式解決方案!

六大模組:

…..

 

 

  1. 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代理,核心包中已經包含此功能!

  1. JDK的動態代理有一個限制,就是使用動態代理的物件必須實現一個或多個介面。如果想代理沒有實現介面的類,就可以使用CGLIB實現。
  2.  CGLIB是一個強大的高效能的程式碼生成包,它可以在執行期擴充套件Java類與實現Java介面。它廣泛的被許多AOP的框架使用,例如Spring AOP和dynaop,為他們提供方法的interception(攔截)。
  3.  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宣告式事務管理

概念

 

  1. 事務是一組操作的執行單元,相對於資料庫操作來講,事務管理的是一組SQL指令,比如增加,修改,刪除等,事務的一致性,要求,這個事務內的操作必須全部執行成功,如果在此過程種出現了差錯,比如有一條SQL語句沒有執行成功,那麼這一組操作都將全部回滾
  2. 事務特性(ACID)
    • Atomic(原子性):要麼都成功,要麼都失敗 
    • Consistent(一致性):資料應該不被破壞
    • Isolate(隔離性):使用者間操作不相混淆
    • Durable(永續性):永久儲存 
    •  

程式中兩種事務管理方式

  1.      程式設計式事務管理
  2.        編寫程式式的事務管理可以清楚的定義事務的邊界,可以實現細粒度的事務控制,比如你可以通過程式程式碼來控制你的事務何時開始,何時結束等,與後面介紹的宣告式事務管理相比,它可以實現細粒度的事務控制,例如jdbc,hibernate,spring中不提倡使用。

 

JDBC事務控制:

con.setAutoCommite (false);   設定事務手動提交

Hibernate中事務控制:

session.beginTransaction();     開啟事務

 

優缺點:

1. 事務控制精確

2. 事務程式碼,與業務邏輯處理程式碼,耦合在一起!

事務程式碼,不能共用! 重新寫事務控制操作!

開發效率低,不便於維護!  (不想用事務,要改程式碼!)

 

 

  1.      宣告式事務管理  (在Spring中使用)
  2.        如果你並不需要細粒度的事務控制,你可以使用宣告式事務,在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"<