JAVA後端面試《Spring》

  • 2020 年 2 月 25 日
  • 筆記

Spring

  1. Spring是什麼?有什麼好處?
  2. IOC是什麼?有什麼好處?簡單過程?
  3. DI是什麼?
  4. IOC和DI的關係?
  5. bean標籤的屬性有哪些?
  6. IOC創建對象有哪幾種方式?
  7. Spring是如何實現IOC的?也就是如何創建對象的?
  8. Spring Bean的生命周期?
  9. 依賴注入DI的方式有幾種?
  10. 註解實現IOC和DI的準備工作有哪些?
  11. 有哪些註解?分別表示什麼含義?
  12. 談談你對Spring AOP的理解?
  13. XML方式實現AOP的通知有幾種?
  14. 註解實現AOP的過程?
  15. 更改多個切面類的執行順序的方法有幾種?
  16. Spring有哪些主要模塊?
  17. Spring中的bean是線程安全的嗎?
  18. Spring支持幾種bean的作用域?
  19. Spring JDBC的實現過程?
  20. 事務的概念是什麼?
  21. 事務的特性有幾個?
  22. 數據庫操作時可能存在的問題有哪些?
  23. 什麼是事務的隔離級別?事務的隔離級別有幾個?
  24. Spring中事務的傳播行為有幾種?
  25. Spring 聲明式事務的實現?

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.*;    /**   * 集合類型賦值   */publicclass 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;      }        @Overridepublic 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"/>
  • ③ 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;    @Repositorypublicclass AccountDaoImpl implements AccountDao {        @Autowiredprivate JdbcTemplate template;        @Overridepublic 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);      }        @Overridepublic 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>
  • 1.賬戶類
package com.wpq.domain;    /**   * 1.賬戶類   */@Datapublicclass Account {        private Integer from;//轉賬者private Integer to;//接收者private Double money;//金額  }  
  • 2.數據訪問類
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.數據訪問類  */@Repositorypublicclass AccountDaoImpl implements AccountDao {        @Autowiredprivate JdbcTemplate template;        @Overridepublic 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);      }        @Overridepublic 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);      }  }  
  • 3.業務處理類
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.業務處理類  */@Servicepublicclass AccountServiceImpl implements AccountService {        @Autowiredprivate AccountDao accountDao;        //轉賬業務最起碼分為2步:從A賬戶減錢;在B賬戶加錢;//可以人為製造異常:int i = 10 / 0;來檢驗此方法是否具備事務功能@Overridepublic void transfer(Integer from, Integer to, Double money) {            System.out.println("service層...轉賬業務...");          accountDao.subMoney(from, money);          //int i = 10 / 0;          accountDao.addMoney(to, money);      }    }  
  • 4.用戶訪問類
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.用戶訪問類   */@Controllerpublicclass AccountController {        @Autowiredprivate 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)  publicclass AccountServiceImpl implements AccountService {        @Autowiredprivate 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);      }    }  

原文鏈接:

https://blog.csdn.net/weixin_43766298/article/details/104208049