JAVA後端面試《Spring》
- 2020 年 2 月 25 日
- 筆記
Spring
- Spring是什麼?有什麼好處?
- IOC是什麼?有什麼好處?簡單過程?
- DI是什麼?
- IOC和DI的關係?
- bean標籤的屬性有哪些?
- IOC創建對象有哪幾種方式?
- Spring是如何實現IOC的?也就是如何創建對象的?
- Spring Bean的生命周期?
- 依賴注入DI的方式有幾種?
- 註解實現IOC和DI的準備工作有哪些?
- 有哪些註解?分別表示什麼含義?
- 談談你對Spring AOP的理解?
- XML方式實現AOP的通知有幾種?
- 註解實現AOP的過程?
- 更改多個切面類的執行順序的方法有幾種?
- Spring有哪些主要模塊?
- Spring中的bean是線程安全的嗎?
- Spring支持幾種bean的作用域?
- Spring JDBC的實現過程?
- 事務的概念是什麼?
- 事務的特性有幾個?
- 數據庫操作時可能存在的問題有哪些?
- 什麼是事務的隔離級別?事務的隔離級別有幾個?
- Spring中事務的傳播行為有幾種?
- 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