❀ Spring5學習大總結

一樂樂發表於2022-03-07

一、瞭解 Spring 基本介紹、主要思想 IoC/DI

1、瞭解 Spring 基本介紹

(1) Spring是什麼?

Spring 是一個輕量級DI/IoC 和 AOP 容器開源框架,致力於構建致力於構建輕量級的 JavaEE 應用簡化應用開發,本身涵蓋了傳統應用開發,還擴充到移動端,大資料等領域。


(2) Spring有什麼優點?與作用?

① Spring 能幫我們低侵入/低耦合地根據配置檔案 建立及組裝物件之間的依賴關係。

② Spring 面向切面程式設計能幫助我們無耦合的實現日誌記錄,效能統計,安全控制等。

③ Spring 能非常簡單的且強大的宣告式事務管理(通過配置完成事務,不用修改程式碼)。

④ Spring 提供了與第三方資料訪問框架(如 Hibernate、JPA)無縫整合,且自己也提供了一套 JDBC 模板來方便資料庫訪問。

⑤ Spring 提供與第三方 Web(如 Struts1/2、JSF)框架 無縫整合,且自己也提供了一套 Spring MVC 框架,來方便 Web 層搭建。

⑥ Spring 能方便的與如 Java Mail、任務排程、快取框架等技術整合,降低開發難度。



2、主要思想 IoC/DI

Spring 是一個DI容器或IoC容器(DI和IoC 思想差不多)。掌握著建立物件和構建物件之間的依賴控制權

● IoC:Inversion of Control(控制反轉):

一種設計思想。 其本意是是將原本在程式中手動建立物件的控制權,交由 Spring 框架來管理

● DI:Dependency Injection(依賴注入):

一種設計思想具體是指 Spring 建立物件的過程中,將物件依賴屬性(常量,物件,集合)通過配置設值給該物件。




二、掌握Spring 基本使用、Spring 獲取bean物件的方式、Spring 標籤 import的引入配置

1、掌握Spring 基本使用

(1) 依賴jar包:

  • spring-beans.jar
  • spring-core.jar
  • commons-logging.jar

(2) 配置:

  • 建立applicationContext.xml 配置檔案:

  • 配置的約束內容:

    <!-- 配置的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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
        
        <!-- 通過配置的bean元素,告訴Spring的IoC容器,需要管理哪一個類的物件 -->
      <bean id="hello" class="com.shan.hello.Hello">
       		 <!-- 通過property子元素,設定管理物件的屬性的值 -->
        	<property name="password" value="123"/>
        	<property name="username" value="shan"/>
        </bean>
    </beans>  
    

(3) 使用:

	@Test
	void testIoC() throws Exception {
		Hello hello = null;
		//=========================
		//1、載入配置檔案:從classpath路徑去尋找配置檔案,建立資源物件
		Resource resource = new ClassPathResource("applicationContext.xml");	
		//2、建立IoC容器:建立spring的工廠物件(IoC容器物件)
		BeanFactory factory = new XmlBeanFactory(resource);
		//3、從Ioc容器獲取物件:從spring IoC 容器(就是factory 工廠物件)中獲取指定名稱的物件
		hello = (Hello)factory.getBean("hello");
		//=========================
		hello.printUser();
	}

■ 從例子,可以看出,spring不僅幫我們建立物件,還幫我們把物件需要的資料給設定進來(物件的屬性依賴)



2、Spring 獲取bean物件的方式

  • 推薦使用:bean的名稱+型別: T getBean(String name, Class requiredType) 根據bean物件在容器中的 名稱+型別 來獲取

    	@Test
    	void testIoC() throws Exception {
    		Hello hello = null;
    		//=========================
    		//1、載入配置檔案:從classpath路徑去尋找配置檔案,建立資源物件
    		Resource resource = new ClassPathResource("applicationContext.xml");	
    		//2、建立IoC容器:建立spring的工廠物件(IoC容器物件)
    		BeanFactory factory = new XmlBeanFactory(resource);
    		//3、從Ioc容器獲取物件:從spring IoC 容器(就是factory 工廠物件)中獲取指定名稱的物件
    		//方式(推薦): T getBean(String name, Class<T> requiredType) 根據bean物件在容器中的 名稱+型別 來獲取
    		hello = factory.getBean("hello", Hello.class);
    		//=========================
    		hello.printUser();
    	}
    

3、Spring 標籤 import的引入配置

  • 元素:<import resource="com/shan/hello.xml"/> 用於引入spring的配置檔案,相當於js中的元素 <javaScript src=""/>
  • 推薦resource路徑加上字首 classpath
  • 預設情況下,resource 是從 classpath 的跟路徑尋找,舉例:<import resource="classpath:com/shan/hello.xml"/>




三、Spring 核心物件 BeanFactory Bean、Spring的配置方式、瞭解Spring管理bean的原理

1、Spring 核心物件 BeanFactory Bean

  • BeanFactory:是Spring的IoC容器(容器--管理物件的生命週期),生產 bean 物件的工廠,負責配置,建立和管理 bean。

  • bean:被 Spring IoC 容器管理的物件稱之為bean。


2、Spring的配置方式

■ 後設資料的配置有三種方式:

□ XML-based configuration (xml配置檔案)

□ Annotation-based configuration (註解

□ Java-based configuration (基於java-config


3、瞭解Spring管理bean的原理

  • 底層是:反射(獲取構造器例項物件)+內省機制(設定屬性值)

① 通過 Resource 物件載入配置檔案
② 解析配置檔案,得到指定名稱的 bean
③ 解析 bean 元素,id 作為 bean 的名字,class 用於反射得到 bean 的例項
  • 注意:此時,bean 類必須存在一個無引數構造器(且該無參構造器和訪問許可權無關);
④ 呼叫 getBean 方法的時候,從容器中返回物件例項;
■ 結論:就是把程式碼從 JAVA 檔案中轉移到了 XML 中。




四、使用Spring的測試框架

相對於傳統測試方式,spring測試框架會幫我們關閉物件資源,而使用傳統方式,不會正常關閉spring容器。

1、依賴jar包:

  • spring-test.jar
  • spring-context.jar
  • spring-aop.jar
  • spring-expression.jar

2、配置檔案:

■ SpringTestTest5-context.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
     
    <!-- 配置bean物件 -->
	<bean id="someBean" class="com.shan.spring_test.SomeBean"/>
</beans> 

3、測試類:

■ SpringTestTest5 類:

//SpringTest 案例測試

//執行 Spring JUnit5
@SpringJUnitConfig
public class SpringTestTest5 {
	//表示自動按照型別 Spring容器中去找到bean物件,並設定給該欄位
	@Autowired
	private SomeBean bean;
	
	@Test
	void testIoC() throws Exception {
		bean.doWork();
	}
}




五、Spring的核心 IoC(基於xml)

1、ApplicationContext 和 BeanFactory 建立物件的區別

  • BeanFactory 在建立Spring容器的時候,並不會立馬建立容器中管理的Bean物件,需要等到獲取某一個 bean 的時候才會建立該 bean--延遲初始化。(懶載入

  • ApplicationContext 在啟動 Spring 容器的時候就會建立所有的 bean(在 Web 應用使用Application


2、常用例項化bean的方式 和 實現FactoryBean介面例項化的方式

(1)例項化bean的方式:

  • 構造器例項化(bean 中有 無引數構造器),標準、常用

    <!-- 配置bean物件 -->
    <bean id="someBean" class="com.shan.spring_test.SomeBean"/>
    

(2)實現FactoryBean介面例項化的方式:

  • 類要實現介面FactoryBean:

    public class DogFactory implements FactoryBean<Dog>{
    	@Override
    	public Dog getObject() throws Exception {
    		Dog dog = new Dog();
    		return dog;
    	}
    
    	@Override
    	public Class<?> getObjectType() {
    		return Dog.class;
    	}
    }
    
    <!-- 實現 FactoryBean 介面例項化:例項工廠變種, 如整合 MyBatis 框架使用 -->  
    <bean id="dog" class="com.shan._04_factory_bean.DogFactory"/>
    



3、 bean作用域scope、初始化init-method和銷燬destroy-method

(1) bean作用域scope

  • 預設和常用的情況是單例 singleton
<bean id="" class="" scope="作用域"/>
  • 單例和多例: singleton: 單例(預設的作用域) prototype: 多例

  • 在web應用中(request、session、application)

  • globalSession: 一般用於 Porlet 應用環境 , 分散式系統存在全域性 session 概念(單點登入)

  • websocket:將一個bean定義定義到WebSocket的生命週期


(2) bean初始化和銷燬:

  • 屬性init-method="該類中初始化方法名" 和 屬性destroy-method="該類中銷燬方法名"
  • 沒有使用spring的測試框架的話,就不能正常關閉IoC容器,即銷燬bean物件了(可以手動關閉)
<bean id="cat" class="com.shan.lifecycle.Cat" init-method="init" destroy-method="close"/>




六、Spring的核心 DI(基於xml):

\({\color{Violet}{● DI跟IoC差不多啦,細節就是DI還負責管理bean物件的屬性}}\)


1、xml配置注入屬性值:

配置與注入:

  • 常量型別 配置value--->注入setter方法

  • 物件型別 配置ref--->注入setter方法

  • 集合型別 配置各自集合對應的元素...--->注入setter方法

    1、通過XML配置裝配

    (1)XML 自動裝配(不推薦)通過bean元素的屬性 autowire 自動裝配

    ✿(2)setter注入 [ 屬性注入(根據型別區分)]

    ■(常用) 注入常量 value

    	<bean id="person" class="com.shan.di_setter.Person">
    		<property name="name" value="shan"/>
    		<property name="age" value="22"/>
    		<property name="salary" value="10000"/>
    	</bean>
    

    ■(常用) 注入物件 ref

        <bean id="cat" class="com.shan.di_setter2.Cat">
        	<property name="name" value="kity"/>
        </bean>    
    	<bean id="person" class="com.shan.di_setter2.Person">
    		<property name="name" value="shan"/>
    		<property name="age" value="22"/>
    		<property name="cat" ref="cat"/>
    	</bean>
    

    ■ 注入集合

    	<bean id="person" class="com.shan.di_setter3.Person">
    		<!-- set型別 -->
    		<property name="set">
    			<set>
    				<value>set1</value>
    				<value>set2</value>
    			</set>
    		</property>
    		<!-- list型別 -->
    		<property name="list">
    			<list>
    				<value>list1</value>
    			</list>
    		</property>
    		<!-- array型別 -->
    		<property name="array">
    			<array>
    				<value>array1</value>
    			</array>
    		</property>
    		<!-- map型別(字典型別) -->
    		<property name="map">
    			<map>
    				<entry key="key1" value="value1"/>
    			</map>
    		</property>
    		<!-- properties型別(特殊的map型別【key和value都是字串】) -->
    		<property name="prop">
    			<value>
    				p1=v1
    				p2=v2
    			</value>
    		</property>
    	</bean>
    



2、bean元素繼承 (本質是xml配置內容的拷貝)

  • 通過abstract屬性進行抽取

  • 通過parent屬性進行引入

image



3、屬性注入應用---配置資料庫連線池

  • 動態載入配置檔案(db.properties---資料庫連線的配置資訊)

  • <context:property-placeholder/>

  • 使用 ${} 動態引入屬性值


(1) 配置資料庫連線池

	<!-- 配置資料庫連線池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://localhost:3306/springdemo?useSSL=false"/>
		<property name="username" value="root"/>
		<property name="password" value="admin"/>
		<property name="initialSize" value="2"/>
	</bean>

(2) db.properties---資料庫連線的配置資訊


(3) property place holder

● 要是使用標籤Context,需要先引入Context的約束(在beans的基礎進行修改即可):

image


● context:property-placeholder 屬性佔位符
     <!-- 從classpath的根路徑 載入db.properties -->   
     <context:property-placeholder location="classpath:db.properties"/>
● 使用 ${} 動態引入屬性值
	<!-- 配置資料庫連線池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="driverClassName" value="${jdbc.driverClassName}"/>
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
		<property name="initialSize" value="${jdbc.initialSize}"/>
	</bean>




七、Spring使用註解配置

1、註解三要素:註解本身、被貼、第三方程式(賦予註解的特殊功能)

★ 對於IoC註解、DI註解:他們的第三方程式是他們對應的解析器。

  • IoC註解:元件掃描器 <context:component-scan base-package=""/>

  • DI註解:註解配置 <context:annotation-config/>


2、DI 註解:@Autowired、@Resource、@Value

  • value註解的威力:結合動態properties配置檔案引入值變數 例如:@Value("${service.port}")

(1) 通過註解注入屬性值

★ 配置與注入:

  • 常量型別 配置value--->注入@Value

  • 物件型別 配置ref--->注入@Autowired/@Resource

(2) IoC 註解:@Component、@Scope、@PostConstruct、@PreDestroy

★ 使用註解@Component(配置Bean)

//相當於 <bean id="dataSource" class="com.shan.ioc.MyDataSource"/>
@Component("dataSource")
public class MyDataSource {

}

★ bean元件版型:

@Component 泛指元件
@Repository 持久層
@Service 業務層
@Controller 控制層

★ 作用域註解、初始化和銷燬註解:@Scope、@PostConstruct、@PreDestroy

\({\color{Violet}{■ 其中初始化和銷燬註解[依賴:javax.annotation-api.jar]}}\)




八、Spring AOP

1、瞭解AOP思想[面向切面程式設計的思想]、AOP思想的原理

(1) 面向切面程式設計的思想:

利用一種稱為"橫切"的技術,剖開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其命名為"Aspect",即切面。

  • 切面:把一個個的橫切關注點放到某個模組中去,稱之為切面。

  • 那麼每一個的切面都能影響業務的某一種功能, 切面的目的就是功能增強

    如日誌切面就是一個橫切關注點,應用中許多方法需要做日誌記錄的只需要插入日誌的切面即可.

image


(2) AOP思想的原理:動態代理


2、Pointcot語法

  • 找到具體的某個方法--哪個包.哪個類.哪個方法

execution(<修飾符>? <返回型別> <宣告型別>? <方法名>(<引數>) <異常>)

  • 切入點表示式中的萬用字元(看具體的方法,先從方法名位置開始看):

    *:匹配任何部分,但是隻能表示一個單詞。

    ..:可用於全限定名中和方法引數中,分別表示子包和 0 到 N 個引數


3、AOP 開發:

(1) 依賴jar包:

  • spring-aop.jar
  • com.springsource.org.aopalliance.jar [spring5的spring-aop.jar已經包含]
  • com.springsource.org.aspectj.weaver.jar

(2) 配置:

  • 引入AOP的約束:

image


  • AOP的3W-what、where、when

	<!-- AOP 配置:在什麼地點、什麼時機、做什麼 -->
	<!-- 1、what:做什麼增強 -->
	<bean id="transactionManager" class="com.shan.tx.TransactionManager"/>
	
	<aop:config proxy-target-class="false"> <!-- 屬性proxy-target-class配置是否使用真實物件  -->
		<!-- 配置AOP切面 -->  
		<aop:aspect ref="transactionManager"> <!-- 關聯what -->
			<!-- 2、where:在哪些包中的哪些類中的哪些方法上做增強 -->
			<aop:pointcut id="txPoint" expression="execution(* com.shan.service..*Service*.*(..))"/>
			<!-- 3、when:在方法執行的什麼時機做增強 --><!-- 關聯where -->
			<aop:before method="open" pointcut-ref="txPoint"/>
			<aop:after-returning method="commit" pointcut-ref="txPoint"/>
			<aop:after-throwing method="rollback" pointcut-ref="txPoint"/>
			<aop:after method="close" pointcut-ref="txPoint"/>
			<aop:around method="aroundMethod" pointcut-ref="txPoint"/>	
		</aop:aspect>
	</aop:config>



4、AOP增強的分類

■ 根據被增強的方法的執行時機分為:前置增強、後置增強、異常增強、最終增強、環繞增強

  • 前置增強:許可權控制、日誌記錄等 [被增強的方法執行之前]
  • 後置增強:提交事務、統計分析資料結果等 [被增強的方法正常執行之後(中途沒有異常)]
  • 最終增強:回滾事務、記錄日誌異常資訊等 [被增強的方法出現異常]
  • 最終增強:釋放資源等 [finally最後操作]
  • 環繞增強:快取、效能日誌、許可權、事務管理等 [可以自定義在被增強方法的什麼時機執行(返回一個Object,引數processdingJoinpoint)]



5、獲取被增強方法的資訊, 並且可以傳遞給增強方法【引數Joinpoint類

  • Joinpoint類連線點,訪問被增強方法的真實物件,代理物件,方法引數等

  • 可以作為前置、後置、異常、最終增強方法的引數,第一個引數

    //可以作為前置、後置、異常、最終增強方法的引數,**`第一個引數`**	
    public void open(JoinPoint jp) {
    	System.out.println("開啟事務~");
    	System.out.println("代理物件:" +jp.getThis().getClass());
    	System.out.println("目標物件:" +jp.getTarget().getClass());
    	System.out.println("被增強方法的引數:" +Arrays.toString(jp.getArgs()));
    	System.out.println("連線點方法的簽名:" +jp.getSignature());
    	System.out.println("當前連線點的型別:" +jp.getKind());
    }
    

5-2、環繞增強方法呼叫真實物件的方法【引數processdingJoinpoint

  • 引數processdingJoinpoint:是JointPoin 的子類,只能用於環繞增強,作為第一個引數

    還可以呼叫真實物件中被增強的方法。

//呼叫真實物件的方法 ret = pjp.proceed();
public Object aroundMethod(ProceedingJoinPoint pjp) {
		Object ret = null;
		System.out.println("開啟事務~");
		try {
			ret = pjp.proceed();//呼叫真實物件的方法
			System.out.println("呼叫真實物件的方法...~");
			System.out.println("提交事務~");
		} catch (Throwable e) {
			System.out.println("回滾事務~,錯誤資訊:" + e.getMessage());
		}finally {
			System.out.println("關閉資源~");
		}
		return ret;
	}



6、使用註解配置AOP

(1) AOP註解的解析器【第三方程式,賦予註解的特殊功能】:

  • 使用cglib註解:配置屬性proxy-target-class="true"
<!-- what -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- AOP註解的解析器 -->
<aop:aspectj-autoproxy/>

(2) 使用註解@Aspect配置一個AOP切面

  • @Pointcut (配置where)
  • @Before、@AfterReturning、@AfterThrowing、@After、@Around(配置when
@Component@Aspect //配置一個AOP切面
public class TransactionManager {
	
	//where
	//xml:<aop:pointcut id="txPoint" expression="execution(* com.shan.service..*Service*.*(..))"/>
	@Pointcut("execution(* com.shan.service..*Service*.*(..))")
	public void txPoint() {
		
	}
	
	//@Before("txPoint()")
	public void open(JoinPoint jp) {
		System.out.println("開啟事務~");
	}

	//@AfterReturning("txPoint()")
	public void commit() {
		System.out.println("提交事務~");
	}
	//@AfterThrowing(value="txPoint()", throwing="ex")
	public void rollback(Throwable ex) {
		System.out.println("回滾事務~,異常資訊:" +ex.getMessage());
	}
	//@After("txPoint()")
	public void close() {
		System.out.println("關閉資源~");
	}
	
	@Around("txPoint()")
	public Object aroundMethod(ProceedingJoinPoint pjp) {
		Object ret = null;
		System.out.println("開啟事務~");
		try {
			ret = pjp.proceed();//呼叫真實物件的方法
			System.out.println("呼叫真實物件的方法...~");
			System.out.println("提交事務~");
		} catch (Throwable e) {
			System.out.println("回滾事務~,錯誤資訊:" + e.getMessage());
		}finally {
			System.out.println("關閉資源~");
		}
		return ret;
	}
}




九、Spring DAO

1、模板類和基類:

image

image


2、pring JDBC 【JDBCTemplate 模板類】

(1) 依賴jar包:

  • mysql-connector-java.jar 【還可以使用德魯伊連線池:druid.jar】
  • spring-jdbc.jar
  • spring-tx.jar

(2) 總結JdbcTemplate模板類-處理CRUD 操作

//DML操作:
public update(String sql, Object...args)
引數:sql     ?佔位符對應的引數
返回:受影響的行數

//DQL 操作:
public <T>List<T> query(String sql, Object...args, RowMapper<T> rowMapper)
引數:sql     ?佔位符對應的引數     結果集處理器
返回:多行結果集封裝的list

3、模板類JdbcTemplate的問題與解決NameParameterJdbcTemplate

(1) 問題:

● 在模板類JdbcTemplate中使用的佔位符 ?【順序佔位符】,需要數第幾個,然後寫對應的引數,引數多了麻煩
● 面對集合查詢 in查詢時(不確定引數個數), select * from employee where id in .....
  • in 後邊不知道該怎麼寫,是應該寫一個?還是(多少個?,都是不確定的)

(2) 解決:使用NameParameterJdbcTemplate

  • 命名的引數JdbcTemplate模板,其實就是在JdbcTemplate外面套一層。

  • 允許使用 xx 來給佔位引數起名稱,我們需要給名稱xx的位置設定引數。

□ 舉例:

public int countOfActorsByFirstName(String firstName) {
    String sql = "select count(*) from T_ACTOR where first_name = :first_name";
    Map<String, String> namedParameters = Collections.singletonMap("first_name", firstName);
    return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters,  Integer.class);
}




十、Spring ORM --- 整合mybatis框架




十一、Spring tx

1、Spring 的事務管理主要包括 3 個 api:

  • PlatformTransactionManager:根據 TransactionDefinition 提供的事務屬性配置資訊,建立事務
  • TransactionDefinition:封裝事務的隔離級別和超時時間,是否為只讀事務和事務的隔離級別和傳播規則等事務屬性.
  • TransactionStatus:封裝了事務的具體執行狀態。如是否是新開啟事務,是否已經提交事務,設定當前事務為rollback-only.

✿ 記:常用的事務管理器:

  • JDBC/MyBatis:DataSourceTransactionManager
  • Hibernate: HibernateTransactionManager

2、事務傳播規則 TransactionDefinition 和 常用的情況

(1) 事務傳播規則:

在一個事務方法中,呼叫了其他事務的方法,此時事務該如何傳遞,按照什麼規則傳播.

(2) 常用的情況:

■ 情況一:需要尊重/遵從當前事務

  • REQUIRED:(常用)必須存在一個事務,如果當前存在一個事務,則加入到該事務中,否則,新建一個事務.

■ 情況二:不遵從當前事務的

  • REQUIRES_NEW:(常用)不管當前是否存在事務,都會新開啟一個事務.必須是一個新的事務.

■ 情況三:寄生事務(外部事務/內部事務/巢狀事務)

  • NESTED:寄生事務,如果當前存在事務,則在內部事務內執行.如果當前不存在事務,則建立一個新的事務.

3、事務配置(基於xml和註解)

(1) 基於xml:事務增強—本質就是AOP增強what、when、where

	<!-- ===============好比是AOP,事務增強================================== -->
	<!-- 1、what:配置jdbc事務管理器 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!-- 2:when:配置事務管理器增強(環繞增強) --><!-- 關聯what -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="trans"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 3、where:配置切面 --><!-- 關聯when -->
	<aop:config>
		<aop:pointcut id="txPc" expression="execution(* com.shan.service.*Service.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
	</aop:config>

(2) 使用註解配置jdbc事務:tx註解解析器、@Transactional

  • 註解:@Transactional

  • 註解屬性:name、propagation、isolation、timeout、read-only、rollback-for、no-rollback-for

    ■ 註解第三方解析:

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- tx註解解析器 -->
    <tx:annotation-driven transaction-manager="txManager"/>
    

    ■ 註解@Transactional使用:

    @Service@Transactional
    public class AccountServiceImpl implements IAccountService{
    	
    	@Autowired
    	private IAccountDAO dao;
    
    	@Override
    	public void trans(Long outId, Long inId, int money) {
    		dao.transOut(outId, money);
    		int a = 1/0; //算術異常
    		dao.transIn(inId, money);	
    	}
    	
    	//若是有查詢方法,可以再貼註解@Transactional新增註解屬性
    	@Transactional(readOnly = true)
    	public void listXX() {
    		
    	}
    }
    

(3) 事務配置(基於註解+Java Config 配置)

  • 註解:

    \({\color{Blue}{@Configuration}}\) 配置

    \({\color{Blue}{@import(配置子類)}}\)

    \({\color{Blue}{@Bean}}\) 配置建立bean物件

    \({\color{Blue}{@ComponentScan}}\) IoC註解解析器

    \({\color{Blue}{@EnableTransactionManagement}}\) 事務註解解析器

    @Transactional 配置jdbc事務

    @PropertySource 配置引入的屬性檔案資源

    \({\color{Gray}{@Component}}\) 泛指元件

    \({\color{Gray}{@Repository}}\) 持久層

    \({\color{Gray}{@Service}}\) 業務層

    \({\color{Gray}{@Controller}}\) 控制層

    @Value 配置注入屬性值

    @Autowired 配置注入屬性值