JAVA後端面試《Spring》

weixin_43766298發表於2020-02-13

1.Spring是什麼?有什麼好處?

  • 概念: SPring是一個支援控制反轉(IOC)和麵向切面程式設計(AOP)的容器框架。
  • 好處: 兩降低>>>兩支援>>>兩方便
    • ①降低了耦合性,提高了開發速度。
    • ②降低了JAVAEE API的使用難度。
    • ③支援AOP和IOC。
    • ④支援宣告式事務。
    • ⑤方便程式測試。
    • ⑥方便整合其他框架。、

2.IOC是什麼?有什麼好處?簡單過程?

  • IOC: 是Inverse of Control(控制反轉)的簡寫。
  • 好處: 通過IOC,直接把物件建立的權力反轉給Spring容器,降低了物件之間的耦合性。
  • 簡單過程: 程式讀取Spring的XML配置文>>>獲取需要建立物件的bean>>>通過反射機制建立物件的例項。

3.DI是什麼?

  • DI: Dependency Injection(依賴注入)的簡寫。
  • 建立物件例項時,同時為物件注入它所依賴的屬性,相當於把每個bean和bean之間的關係交給Spring容器來管理。

4.IOC和DI的關係?

  • 控制反轉(IOC)和依賴注入(DI)是從不同角度描述同一件事情,利用依賴關係注入的方式,實現對像之間的解耦。
  • 耦合性(耦合度):是對模組間關聯程度的度量。模組之間聯絡越緊密,其耦合性就越高,模組之間越獨立則越低。

5.bean標籤的屬性有哪些?

  • ① id (唯一標識)
  • ② name(獲取bean的鍵)
  • ③ class(指定bean對應類的全路徑)
  • ④ scope(單例或者多例設計模式)
  • ⑤ lazy-init(延時載入,預設值:false):設定false時,只有呼叫getBean方法才會建立物件
  • ⑥ init-method(指定:監聽物件建立的方法)
  • ⑦ destroy-method(指定:監聽物件銷燬的方法)

6.IOC建立物件有哪幾種方式?

  • ①無參構造
  • ②有參構造
  • ③靜態工廠模式(1個bean標籤)
  • ④非靜態工廠模式(2個bean標籤)
//1.無參構造
   <bean id="user" class="com.wpq.pojo.User"></bean>
  //在bean標籤內部使用property標籤,相當於呼叫set方法. name:要賦值的屬性的屬性名 value:值
   <bean id="user" class="com.wpq.pojo.User">
        <property name="name" value="zs"></property>
        <property name="password" value="123"></property>
   </bean>
                 
//2.有參構造
 <bean id="user" class="com.wpq.pojo.User">
     <constructor-arg index="0" type="java.lang.String" name="name" value="張三"></constructor-arg>
     <constructor-arg index="1" type="java.lang.String" name="password" value="123"></constructor-arg>
 </bean>
//3.靜態工廠模式--createPerson()為靜態方法
<bean name="personFactory" class="com.wpq.factory.PersonFactory" factory-method="createPerson"/>
//4.工廠模式
  <!--1.建立出工廠物件-->
  <bean name="personFactory" class="com.wpq.factory.PersonFactory"/>
  <!--2.呼叫工廠的instancePerson()方法建立出Person物件-->
  <bean name="person" factory-bean="personFactory" factory-method="instancePerson"/>

7.Spring是如何實現IOC的?也就是如何建立物件的?

    <!--0.物件建立原理:xml解析+反射-->
    <!--1.ClassPathXmlApplicationContext根據xml的路徑和名稱載入xml;-->
    <!--2.對該xml檔案進行解析-->
    <!--3.根據class屬性,獲取class屬性的值:com.wpq.domain.Person-->
    <!--4.反射:獲取位元組碼的方式,Class clazz=Class.forName("全路徑");p.getClass();Person.class-->
    <!--5.根據位元組碼建立物件:Person p=clazz.newInstance()-->
    <!--6.給物件裡的屬性賦值:Fields[] fields=clazz.getDeclaredFields();-->
    <!--7.遍歷屬性陣列:for(Field field : fields){ field.setAccessable(true);field.set(30)}-->
    <bean id="person" class="com.wpq.domain.Person">
        <property name="name" value="zs"/>
        <property name="age" value="30"/>
    </bean>

8.Spring Bean的生命週期?

  • ①例項化 Instantiation
  • ②屬性賦值 Populate
  • ③初始化 Initialization
  • ④銷燬 Destruction
    在這裡插入圖片描述

9.依賴注入DI的方式有幾種?

  • ①set方法注入
<bean id="user" class="com.wpq.pojo.User">
        <property name="name" value="zs"></property>
        <property name="password" value="123"></property>
   </bean>
  • ②建構函式注入
<bean id="user" class="com.wpq.pojo.User">
     <constructor-arg index="0" type="java.lang.String" name="name" value="張三"></constructor-arg>
     <constructor-arg index="1" type="java.lang.String" name="password" value="123"></constructor-arg>
 </bean>
  • ③P名稱空間注入
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--第3種注入方式:p名稱空間,記得引入一個名稱空間字串:xmlns:p="http://www.springframework.org/schema/p"-->
    <!--p:property的縮寫!簡化了set方式注入的程式碼編寫-->
   <bean name="car" class="com.wpq.domain.Car" p:logo="馬車" p:color="黑色"/>
   <bean name="person" class="com.wpq.domain.Person" p:name="阮小二" p:age="40" p:car-ref="car"/>
</beans>
  • ④spel表示式注入
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--4.第4種spel表示式來注入值-->
    <bean name="car" class="com.syc.spring.domain.Car">
        <property name="logo" value="勞斯萊斯"/>
        <property name="color" value="黑色"/>
    </bean>

    <bean name="person" class="com.wpq.domain.Person">
        <!--spel語法:#{變數名稱}-->
        <property name="name" value="#{car.logo}"/>
    </bean>
</beans>
  • ⑤複雜型別(集合)注入
package com.wpq.domain;

import java.util.*;

/**
 * 集合型別賦值
 */
public class CollectionBean {

    //array節點
    private Object[] arr;

    //list節點
    private List list;

    //map節點
    private Map map;

    //set節點
    private Set set;

    //Properties:配置屬性,props節點
    private Properties props;

    public Object[] getArr() {
        return arr;
    }

    public void setArr(Object[] arr) {
        this.arr = arr;
    }

    public List getList() {
        return list;
    }

    public void setList(List list) {
        this.list = list;
    }

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    public Set getSet() {
        return set;
    }

    public void setSet(Set set) {
        this.set = set;
    }

    public Properties getProps() {
        return props;
    }

    public void setProps(Properties props) {
        this.props = props;
    }

    @Override
    public String toString() {
        return "CollectionBean{" +
                "arr=" + Arrays.toString(arr) +
                ", list=" + list +
                ", map=" + map +
                ", set=" + set +
                ", props=" + props +
                '}';
    }

}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--5.第5種注入方式:複雜(集合)型別注入-->
    <bean name="cb2" class="com.wpq.domain.CollectionBean">
        <property name="arr">
            <array>
                <value>李師師</value>
                <value>柳如是</value>
                <value>蒼老師</value>
            </array>
        </property>
    </bean>

    <bean name="cb3" class="com.wpq.domain.CollectionBean">
        <property name="list">
            <list>
                <value>大喬</value>
                <value>小喬</value>
                <value>金蓮</value>
            </list>
        </property>
    </bean>

    <bean name="cb4" class="com.wpq.domain.CollectionBean">
        <property name="map">
            <map>
                <entry key="name" value="三胖"/>
                <entry key="age" value="30"/>
                <entry key="job" value="boss"/>
            </map>
        </property>
    </bean>

    <bean name="cb5" class="com.wpq.domain.CollectionBean">
        <property name="set">
           <set>
               <value>大喬</value>
               <value>小喬</value>
               <value>金蓮</value>
           </set>
        </property>
    </bean>

    <bean name="cb6" class="com.wpq.domain.CollectionBean">
        <property name="props">
            <props>
                <prop key="url">jdbc:mysql://localhost:3306/db01</prop>
                <prop key="driver">com.jdbc.mysql.Driver</prop>
                <prop key="username">root</prop>
                <prop key="password">root</prop>
            </props>
        </property>
    </bean>

</beans>

10.註解實現IOC和DI的準備工作有哪些?

  • ① 在XML檔案中引入Context的約束
  • ② 配置元件掃描器
  • ③使用註解
<?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">
     <!--1.在XML檔案中引入Context的約束-->
    <!--2.配置元件掃描器:去指定的包裡面掃描要建立的物件-->
    <context:component-scan base-package="com.wpq.domain,com.wpq.web,com.wpq.service,com.wpq.dao"/>

</beans>

11.有哪些註解?分別表示什麼含義?

  • ①註解實現IOC
    • @Component:元件註解,用來建立一個物件,等同於在xml中寫了bean標籤。
  • ②註解實現DI
    • @Value("…"): 只能給簡單型別注入值,不能給引用型別注入值,使用在成員變數上或set方法上 (簡單型別=String+8種基本型別)
      • 注意:該註解可以引入配置檔案中的變數。 語法: @Value("${age}")
實現步驟: 1. 建立conf.properties配置檔案(age=11,name=wpq)
          2. XML中配置property-placeholder載入配置檔案 
           <!--用來去某個指定的位置下,載入指定名稱的配置檔案-->
   		<!--會把這個properties檔案轉換為一個Properties類-->
   		<context:property-placeholder location="classpath:conf.properties"/>
  • @Autowired: 自動裝載物件,預設情況下是按照型別來進行匹配。
  • @Qualifier: 該註解一般要結合@Autowired的一起使用,當@Autowired根據型別無法匹配物件的時候,進行輔助,根據名稱進行依賴注入.解決無法根據型別進行唯一性物件匹配的問題.
  • @Resource: 等同於@Autowired+@Qualifier,該註解是Java原生的註解,既可以根據型別,又可以根據名稱進行依賴注入.
  • ③ Bean標籤的屬性對應的註解
    • 作用域: @Scope(scopeName=“單例/多例”)
    • 延遲載入:@Lazy: 等同於中的lazy-init屬性 ,設定是否延遲載入
    • 建立物件監聽:@PostConstruct 指定監聽物件建立的方法
    • 銷燬物件監聽:@PreDestroy 指定監聽物件銷燬的方法
  • ④ 元件註解
    • @Component:元件註解
    • @Controller:元件註解,一般用於web層物件的建立
    • @Service:元件註解,一般用於service層物件的建立
    • @Repository:元件註解,一般用於dao層物件的建立
  • ⑤ 測試註解
    • @RunWith(SpringJUnit4ClassRunner.class) :括號內指定完成測試工作的類
    • @ContextConfiguration(“classpath:appication-Collection.xml”) : 指定要載入的XML配置檔案
    • @Test :寫在測試方法上
  • ⑥ 元註解
    • @Target(ElementType.FIELD):定義註解的作用範圍
    • @Retention(RetentionPolicy.RUNTIME):定義註解的生命週期(保留策略)
    • 自定義註解:必須帶上面兩個元註解

12.談談你對Spring AOP的理解?

  • ① 概念:是Aspect Oriented Programming的簡寫,翻譯過來就是面向切面程式設計。
  • ② 核心思想:AOP把系統分為核心關注點和橫切關注點兩個部分,將應用程式中的業務邏輯同為其提供支援的通用服務進行分離。
    • 核心關注點:就是業務處理的主要流程(縱向的業務邏輯處理)
    • 橫切關注點:就是出現在每個業務邏輯處理模組中的大量重複程式碼,比如說許可權認證,日誌,事務處理。
  • ③ AOP解決的問題:避免了出現大量的重複性程式碼,提高了程式碼的複用性。
  • ④ AOP底層使用的兩種機制:JDK的動態代理和Java類庫的CGLIB代理。
    • 如果我們類實現了介面,Spring底層實現AOP就會呼叫動態代理,否則就呼叫CGLIB代理。
      在這裡插入圖片描述

13.XML方式實現AOP的通知有幾種?

  • ① 前置通知 before
  • ② 環繞通知 around
  • ③ 後置通知 after-Returning
  • ④ 異常通知 after-Throwing
  • ⑤ 最終通知 after

14.註解實現AOP的過程?

       1.配置Spring XML檔案
       	  開啟自動代理 <aop:aspectj-autoproxy/> :宣告自動為spring容器中那些配置@Aspect切面的bean建立代理,織入切面
          開啟元件掃描 <context:component-scan base-package="com.wpq.Spring"/>
       2.建立切面類:給類上面新增@Aspect註解  
  	   3.切面類中配置切入點 :@Pointcut(value = "execution(* com.wpq.service.impl.*.*(..))")
                              public void pointCut() {}
	   4.在切面類不同的方法中新增註解:
		  前置:@Before(value=“pointCut()”)
		  環繞: @Around(value=“pointCut()”)
		  後置: @AfterReturning(value=“pointCut()”)
		  異常: @AfterThrowing(value=“pointCut()”)
		  最終: @After(value=“pointCut()”)

15.更改多個切面類的執行順序的方法有幾種?

  • ① 預設按照類的首字母來執行,a-z/A-Z
  • ② 給切面類新增 @Order(v) 註解,v越小,優先順序越高
  • ③ 切面類實現Order介面,重寫getOrder()方法

16.Spring有哪些主要模組?

  • Spring框架至今已經整合了20多個模組。主要是核心容器、資料訪問/整合、Web、AOP、工具、訊息和測試模組。
    在這裡插入圖片描述

17.Spring中的bean是執行緒安全的嗎?

  • Spring容器中的Bean是否執行緒安全,容器本身並沒有提供Bean的執行緒安全策略,因此可以說spring容器中的Bean本身不具備執行緒安全的特性,但是還是要結合具體的scope的Bean去研究。

18.Spring支援幾種bean的作用域?

  • ① singleton 單例模式 (Scope預設):@Scope(value = “singleton”)
  • ② prototype 多例模式:每次獲取Bean的時候會有一個新的例項
  • ③ request: request表示該針對每一次HTTP請求都會產生一個新的bean,同時該bean僅在當前HTTP request內有效
  • ④ session:該作用域表示該針對每一次HTTP請求都會產生一個新的bean,同時該bean僅在當前HTTP session內有效
  • ⑤ global session:該作用域類似於標準的HTTP Session作用域,不過它僅僅在基於portlet的web應用中才有意義。Portlet規範定義了全域性Session的概念,它被所有構成某個 portlet web應用的各種不同的portlet所共享。在global session作用域中定義的bean被限定於全域性portlet Session的生命週期範圍內。如果你在web中使用global session作用域來標識bean,那麼web會自動當成session型別來使用。

19.Spring JDBC的實現過程?

  • ① 新增spring-orm依賴包(SpringJDBC、mybatis、hibernate的必須依賴包)
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>${spring.version}</version>
</dependency>
  • ② 建立JdbcTemplate物件
1.封裝一個xxxDao(UserDao)類,在類中直接通過自動裝配註解注入
    @Autowired
    private JdbcTemplate jdbcTemplate; <先建立物件>
2.建立Spring XML配置檔案 <把建立JdbcTemplate物件的權利交給Spring> 

<?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" 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.開啟元件掃描-->
				<context:component-scan base-package="com.wpq.dao"/>
                 <!--2.引入配置檔案-->
				<context:property-placeholder location="xxx.properties" />
				 <!--3.建立連線池物件-->
				 <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
					 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
					 <property name="driverClass" value ="${jdbc.driverClass}"/>
					 <property name="user" value=" ${jdbc.user}"/>
					 <property name="password" value="${jdbc.password}"/>
				 </bean>	
                 <!--4.建立模板物件-->				 
				 <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
				   <!--引用上面建立的連線池物件-->				
				   <property name="dataSource" ref="dataSource"/>
				 </bean> 
</beans>
  • ③ 使用JdbcTemplate物件
package com.wpq.dao.impl;

import com.wpq.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate template;

    @Override
    public void subMoney(Integer id, Double money) {
        System.out.println("賬戶:" + id + ",減錢了..." + money);
        String sql = "update tb_account set money=money - ? where id=?";
        template.update(sql, money, id);
    }

    @Override
    public void addMoney(Integer id, Double money) {
        System.out.println("賬戶:" + id + ",加錢了..." + money);
        String sql = "update tb_account set money=money + ? where id=?";
        template.update(sql, money, id);
    }
}

20.事務的概念是什麼?

  • 事務是一組原子性的SQL查詢,或者說是一個獨立的工作單位。(要麼全部成功,要麼全部失敗)

21.事務的特性有幾個?

  • ① 原子性(atomicity):指處於同一個事務中的多條SQL查詢是不可分割的,要麼全部提交成功,要麼全部提交失敗回滾。
  • ② 一致性(consistency):事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。比如轉賬,轉賬前兩個賬戶餘額之和為2k,轉賬之後也應該是2K。
  • ③ 隔離性(isolation):指多執行緒環境下,一個事務所做的修改在最終提交以前,對其它事務是不可見的。
  • ④ 永續性(durability):事務一旦提交,則其所做的修改就會永久儲存到資料庫中。

22.資料庫操作時可能存在的問題有哪些?

  • ① 髒讀:指一個執行緒中的事務讀取到了另外一個執行緒中事務未提交的資料。
  • ② 不可重複讀:指一個執行緒中的事務讀取到了另外一個執行緒中事務提交的update的資料,讀取到之前查詢一次,讀取到之後查詢一次,兩次查詢結果不一樣。
  • ③ 幻讀:指的是當A事務在讀取某個範圍內的記錄時,B事務又在該範圍內插入了新的記錄,當A事務再次讀取該範圍的記錄時,會產生幻行(指一個執行緒中的事務讀取到了另外一個執行緒中事務提交的insert資料)。

23.什麼是事務的隔離級別?事務的隔離級別有幾個?

  • 概念: 指的是一個事務對資料的修改與另一個併發的事務的隔離程度。當多個事務同時訪問相同資料時,如果沒有采取必要的隔離機制,就可能發生髒讀,不可重複讀和幻讀的問題。
  • ① READ UNCOMMITTED 未提交讀(最低階別)
  • ② READ COMMITTED 提交讀–>解決了髒讀
  • ③ REPEATABLE READ 可重複讀 (MySQL的預設) -->解決了髒讀和不可重複讀
  • ④ SERIALIZABLE 可序列化 (最高階別) -->解決了髒讀,不可重複讀和幻讀

24.Spring中事務的傳播行為有幾種?

  • ① PROPAGATION_REQUIRED(預設) :表示當前方法必須執行在事務中
  • ② PROPAGATION_REQUIRED_NEW:表示當前方法必須執行在它自己的事務中
  • ③ PROPAGATION_SUPPORTS :表示當前方法不需要事務上下文,但是如果存在當前事務的話,那麼該方法會在這個事務中執行
  • ④ PROPAGATION_NOT_SUPPORTED: 表示該方法不應該執行在事務中
  • ⑤ PROPAGATION_NEVER: 表示當前方法不應該執行在事務上下文中
  • ⑥ PROPAGATION_NESTED: 表示如果當前已經存在一個事務,那麼該方法將會在巢狀事務中執行
  • ⑦ PROPAGATION_MANDATORY:表示該方法必須在事務中執行,如果當前事務不存在,則會丟擲一個異常

25.Spring 宣告式事務的實現?

  • ① 傳統事務實現方案:利用JDBC通過手動編寫事務相關程式碼來實現。
        try{
            beginTransaction();
            業務程式碼;
            commit();
        }catch (Exception e){
            rollback();
        }
  • ② Spring實現宣告式事務的原理:AOP
  • ③ 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"
       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">
                 <!--開啟元件掃描-->
				<context:component-scan base-package="com.wpq"/>
                 <!--引入配置檔案-->
				<context:property-placeholder location="xxx.properties" />
				 <!--建立連線池物件-->
				 <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
					 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
					 <property name="driverClass" value ="${jdbc.driverClass}"/>
					 <property name="user" value=" ${jdbc.user}"/>
					 <property name="password" value="${jdbc.password}"/>
				 </bean>	
     1.配置一個事務管理器
		<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
					<!--將事務管理器,與我們上面定義的資料來源繫結在一起.-->
					<property name="dataSource" ref="dataSource"/>
		</bean>
     2.配置一個事務切面類,配置事務規則
		<tx:advice id="txAdvice" transaction-manager="transactionManager">
					<tx:attributes>
							
							<!--給service層中,名稱是transfer開頭的所有的方法新增事務!-->
							<tx:method name="transfer**" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
							
							<!--給service層中所有的增刪改方法,新增事務-->
							<tx:method name="add**"/>
							<tx:method name="delete**"/>
							<tx:method name="update**"/>
							
							<!--對查詢方法進行事務處理-->
							<tx:method name="select**" propagation="SUPPORTS" read-only="true"/>
					</tx:attributes>
		</tx:advice>  
					
     3.把目標類和切面類整合在一起
		<aop:congfig>
					
		     <!--事務新增在業務層,保證業務層的正確執行,
		     expression:切入點表示式,指定要新增事務功能的某個路徑下的類中的方法-->
		     
			 <aop:pointcut id="pointCut" expression="execution(* com.wpq.service.impl.*.*(..))"/>
					
			<!--advice-ref:用來引用一個關於事務切面的增強通知方法-->
			<aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
		</aop:config> 
    4.實現自己的service層業務程式碼
</beans>
package com.wpq.domain;

/**
 * 1.賬戶類
 */
@Data
public class Account {

    private Integer from;//轉賬者
    private Integer to;//接收者
    private Double money;//金額
}

package com.wpq.dao.impl;

import com.wpq.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
/**
*2.資料訪問類
*/
@Repository
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate template;

    @Override
    public void subMoney(Integer id, Double money) {
        System.out.println("賬戶:" + id + ",減錢了..." + money);
        String sql = "update tb_account set money=money - ? where id=?";
        template.update(sql, money, id);
    }

    @Override
    public void addMoney(Integer id, Double money) {
        System.out.println("賬戶:" + id + ",加錢了..." + money);
        String sql = "update tb_account set money=money + ? where id=?";
        template.update(sql, money, id);
    }
}
package com.wpq.service.impl;

import com.wpq.dao.AccountDao;
import com.wpq.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*3.業務處理類
*/
@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    //轉賬業務最起碼分為2步:從A賬戶減錢;在B賬戶加錢;
    //可以人為製造異常:int i = 10 / 0;來檢驗此方法是否具備事務功能
    @Override
    public void transfer(Integer from, Integer to, Double money) {
      
        System.out.println("service層...轉賬業務...");
        accountDao.subMoney(from, money);
        //int i = 10 / 0;
        accountDao.addMoney(to, money);
    }

}

package com.wpq.web;

import com.wpq.domain.Account;
import com.wpq.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * 4.使用者訪問類
 */
@Controller
public class AccountController {

    @Autowired
    private AccountService accountService;

    @RequestMapping("/trans")
    public void transfer(Account account) {
        System.out.println("web層...轉賬介面...");
        accountService.transfer(account.getFrom(), account.getTo(), account.getMoney());
    }


}

  • ④ 註解方式實現宣告式事務
<?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" 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">
                 <!--開啟元件掃描-->
				<context:component-scan base-package="com.wpq"/>
                 <!--引入配置檔案-->
				<context:property-placeholder location="xxx.properties" />
				 <!--建立連線池物件-->
				 <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
					 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
					 <property name="driverClass" value ="${jdbc.driverClass}"/>
					 <property name="user" value=" ${jdbc.user}"/>
					 <property name="password" value="${jdbc.password}"/>
				 </bean>	       

1.XML中配置一個事務管理器
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
			<!--將事務管理器,與我們上面定義的資料來源繫結在一起.-->
			<property name="dataSource" ref="dataSource"/>
	</bean>   			
2.XML中開啟事務的註解功能
    <tx:annotation-driven/>			
3.在業務類或者業務方法上面新增註解
	@Transactional(isolation =Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED)
</beans>
package com.wpq.service.impl;

import com.wpq.dao.AccountDao;
import com.wpq.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*3.業務處理類
*@Transactional註解寫在類上方:表示給當前類中所有業務方法開啟事務
*@Transactional註解寫在類中的某個方法上:表示給當前業務方法開啟事務
*/
@Service
@Transactional(isolation =Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED)
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    //轉賬業務最起碼分為2步:從A賬戶減錢;在B賬戶加錢;
    //可以人為製造異常:int i = 10 / 0;來檢驗此方法是否具備事務功能
    @Override
    //@Transactional(isolation =Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED)
    public void transfer(Integer from, Integer to, Double money) {
      
        System.out.println("service層...轉賬業務...");
        accountDao.subMoney(from, money);
        //int i = 10 / 0;
        accountDao.addMoney(to, money);
    }

}

相關文章