1. 程式人生 > 其它 >靜態庫和動態庫的區別

靜態庫和動態庫的區別

Spring

1.Spring簡介

使現有的技術更加容易使用,本身是一個大雜燴,整合了現有的所有技術

SSH:Struct2 + Spring + Hibernate

SSM:SpringMVC + Spring + Mybatis

官方文件:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans

官網:https://spring.io/

官方下載:https://repo.spring.io/ui/native/release/org/springframework/spring/

github地址:https://github.com/spring-projects/spring-framework

<!--maven-->

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.19</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.19</version>
</dependency>

優點:開源免費的容器,輕量級的非入侵式的框架,支援事務的處理,對框架整合的支援

兩大特性:控制反轉(IOC)、面向切面程式設計(AOP)

  • Spring Boot:
    • 一個快速開發的腳手架
    • 基於SpringBoot可以快速開發單個微服務
    • 約定大於配置
  • Spring Cloud:
    • SpringCloud是基於SpringBoot實現的

2.IOC理論

1.基本原理

之前,程式是主動建立物件!控制權在程式手上;使用了set注入後,程式不再具有主動性,而是變成了被動的接受物件

//通過利用介面來達到使用者決定    

private UserDao userDao;

public void setUserDao(UserDao userDao){
      this.userDao = userDao;
      userDao.test();
}

控制反轉(IOC)是一種設計思想,依賴注入(DI)是實現IOC的一種方法,也有人認為DI只是IOC的另一種說法。沒有IOC的程式中,我們使用面向物件程式設計,物件的建立與物件間的依賴關係完全硬編碼在程式中,物件的建立由程式自己控制,控制反轉後將物件的建立轉移給第三方,可以理解為:獲得依賴物件的方式反轉了。

採用XML方式配置Bean的時候,Bean的定義資訊是和實現分離的,而採用註解的方式可以把兩者合二為一,Bean的定義資訊直接以註解的形式定義在實現類中,從而達到了零配置的目的

控制反轉是一種通過描述(XML或註解)並通過第三方去生產或獲取特定物件的方式。在Spring中實現控制反轉的是IOC容器,其方法是依賴注入(DI)。

本質上是將物件交給Spring託管,由Spring負責建立、管理、裝配。也就是說修改需求只需要在配置檔案中修改,不需要對程式碼做改動。

2.一些配置

  • 別名
<alias name="oldName" alias="newName"/>
  • bean配置
<!--id為新建的物件名,class為對應的實體類,name可以起別名,同時可以取多個,property對應形參-->

<bean id="oldName" class="com.Gw.pojo.user" name="newName1 newName2,newName3...">
	<property name="name" value="yGw"></property>
</bean>
  • import

一般用於團隊開發,將多個xml合併為一個applicationContext.xml

<import resource="beans1.xml"></import>
<import resource="beans2.xml"></import>
<import resource="beans3.xml"></import>

3.依賴注入

1.構造器注入

在配置檔案載入的時候,容器中所有的物件都已經載入了(呼叫建構函式)

1.預設使用無參構造

2.如果要使用有參構造

  • 下標賦值
<bean id="user" class="com.Gw.pojo.User">
    <constructor-arg index="0" value="Gw"/>
</bean>
  • 型別
<bean id="user" class="com.Gw.pojo.User">
    <!--對於引用型別必須指明具體-->
    <constructor-arg type="java.lang.String" value="Gw2"/>
</bean>
  • 引數名
<bean id="user" class="com.Gw.pojo.User">
    <constructor-arg name="name" value="Gw3"/>
</bean>

2.Set方式注入

  • 依賴:bean物件的建立依賴於容器!
  • 注入:bean物件中的所有屬性由容器來注入!
<!--常見的幾種注入-->
<bean id="address" class="com.Gw.pojo.Address">
    <property name="address" value="chengdu"></property>
</bean>
<bean id="student" class="com.Gw.pojo.Student">
    
    <!--第一種,普通注入-->
    <property name="name" value="ygw"/>

    <!--第二種,Bean注入-->
    <property name="address" ref="address"/>

    <!--第三種,陣列注入-->
    <property name="books">
        <array>
            <value>紅樓夢</value>
            <value>西遊記</value>
            <value>水滸傳</value>
            <value>三國演義</value>
        </array>
    </property>
    
	<!--list注入-->
    <property name="hobbys">
        <list>
            <value>聽歌</value>
            <value>敲程式碼</value>
            <value>打遊戲</value>
            <value>刷視訊</value>
        </list>
    </property>
    
    <!--map注入-->
    <property name="card">
        <map>
            <entry key="卡1" value="123456"></entry>
            <entry key="卡2" value="123456"></entry>
            <entry key="卡3" value="123456"></entry>
        </map>
    </property>
    
    <!--set注入-->
    <property name="games">
        <set>
            <value>Naraka</value>
            <value>ReadyOrNot</value>
            <value>CS:GO</value>
        </set>
    </property>
    
    <!--null注入-->
    <property name="wife">
        <null/>
    </property>
    
    <!--properties注入-->
    <property name="info">
        <props>
            <prop key="學號">202013160322</prop>
            <prop key="性別">男</prop>
            <prop key="姓名">ygw</prop>
        </props>
    </property>
</bean>

3.拓展方式注入

p名稱空間注入

<bean id="user" class="com.Gw.pojo.User" p:name="ygw" p:age="20"/>

在使用前需要加入約束

xmlns:p="http://www.springframework.org/schema/p"

c名稱空間注入

<bean id="user2" class="com.Gw.pojo.User" c:name="smart" c:age="21"/>

使用前加入約束

xmlns:p="http://www.springframework.org/schema/p"

4.Bean的作用域

  • 單例模式(Spring預設)
<!--將scope設定為singleton,呼叫多次時不重複生成物件-->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
  • 原型模式
<!--將scope設定為prototype,呼叫時重新生成物件-->
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

其他的request、session、application、websocket在web中應用

4.Bean的自動裝配

  • byName
<!--byName使用時需要保證所有bean的id唯一,並且這個bean需要和自動注入的屬性的set方法的值一致-->

<bean id = "cat" class = "com.Gw.pojo.Cat"/>
<bean id = "dog" class = "com.Gw.pojo.Dog"/>

<bean id = "people" class = "com.Gw.pojo.people" autowire = "byName">
	<property name = "name" value = "ygw"/>
</bean>
  • byType
<!--byType使用時需要保證所有bean的class唯一,並且這個bean需要和自動注入的屬性的set方法的值一致-->

<!--id可省略-->
<bean class = "com.Gw.pojo.Cat"/>
<bean class = "com.Gw.pojo.Dog"/>

<bean id = "people" class = "com.Gw.pojo.people" autowire = "byName">
	<property name = "name" value = "ygw"/>
</bean>

1.註解實現自動裝配

註解注入在XML注入之前執行。因此,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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

2.@Autowired與@Resource

1.聯絡

  • @Autowired和@Resource註解都是作為bean物件注入的時候使用的
  • 兩者都可以宣告在欄位和setter方法上

注意:如果宣告在欄位上,那麼就不需要再寫setter方法。但是本質上,該物件還是作為set方法的實參,通過執行set方法注入,只是省略了setter方法罷了

2.區別

  • @Autowired註解是Spring提供的,而@Resource註解是J2EE本身提供的
  • @Autowird註解預設通過byType方式注入,而@Resource註解預設通過byName方式注入
  • @Autowired註解注入的物件需要在IOC容器中存在,否則需要加上屬性required=false,表示忽略當前要注入的bean,如果有直接注入,沒有跳過,不會報錯

3.使用

  • @Autowird預設的注入方式為byType,也就是根據型別匹配,當有多個實現時,則通過byName注入,也可以通過配合@Qualifier註解來顯式指定name值,指明要使用哪個具體的實現類,如果需要設定物件為空可以用註解@nullable或者將required設定為false
public class People {
    
    @Autowired
    @Qualifier(name="cat1")
    private Cat cat;
    
    @Autowired
    @nullable
    private Dog dog;
    
    String name;

    public Cat getCat() {
        return cat;
    }
    public Dog getDog() {
        return dog;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  • @Resource首先通過byName匹配,當無法匹配IOC容器中任何一個id,於是通過byType匹配,如果型別的實現類有兩個,仍然無法確定,於是報錯。同時@Resource還有兩個重要的屬性:nametype,用來顯式指定byName和byType方式注入;當指定某種方式匹配時,如果匹配不到則直接報錯
@Resource(name=""/type="")
private Dog dog;

5.使用註解開發

說明:在Spring4之後使用註解必須要aop包,xml更加萬能,維護更加方便;最好是xml用來管理bean,註解只負責屬性的注入

使用註解前需要加入:

<!--包中填寫需要掃描的內容-->
<context:component-scan base-package="com.Gw"/>
<context:annotation-config/>

@Component的衍生註解,@Component可以看做<bean id="" class=""~>

  • @Repository -- Dao層
  • @Service -- Service層
  • @Controller -- Controller層

@Value可以看做<property><value></value~> </property~>

@Scope用來設定作用域@Scope("singleton/prototype/....")

@Component
public class User {
    @Value("ygw")
    private String name;

    public String getName() {
        return name;
    }
}

6.使用Java方式配置Spring

//Configuration本質上就是Component,@Configuration可以等價於applicationContext.xml
@Configuration
@ConponentScan("com.Gw.pojo")  //掃描包
@Import("Myconfig2.class")  //引入其他包
public class Myconfig {

    //等價於<bean id = "getUser" class = "com.Gw.pojo.User"/>
    @Bean
    @Value("ygw")
    public User getUser(){
        return new User();
    }
}

//如果完全使用了配置類去做,則配置的使用通過AnnotationConfigApplicationContext獲取上下文
@Test
public void test1(){
    ApplicationContext context = new AnnotationConfigApplicationContext(Myconfig.class);
    User user = context.getBean("getUser", User.class);
    System.out.println(user.getName());
}

7.動態代理

動態代理主要會用到Proxy和InvocationHandler

  • InvocationHandler(動態代理)
//InvocationHandler是一個介面,定義了invoke方法,invoke是生成proxy例項的方法
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
  • Proxy(代理人)
Modifier and Type Method and Description
static InvocationHandler getInvocationHandler(Object proxy)Returns the invocation handler for the specified proxy instance.
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)Returns the java.lang.Class object for a proxy class given a class loader and an array of interfaces.
static boolean isProxyClass(Class<?> cl)Returns true if and only if the specified class was dynamically generated to be a proxy class using the getProxyClass method or the newProxyInstance method.
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.

舉例說明,在原有業務UserService的基礎上加上日誌輸出

package com.Gw.demo01;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//動態代理的實現
public class ProxyInvocationHandler implements InvocationHandler {

    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    
	//最最最最重要的方法,在使用getProxy()方法時,給出的InvocationHandler是this,也就是說代理人在動態的執行userService中的方法時會呼叫當前類的invoke方法,在這個方法中用method.invoke()來呼叫代理物件的方法
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target, objects);
        return result;
    }

    public void log(String msg){
        System.out.println("[debug] 執行了" + msg +"方法");
    }
}

import com.Gw.demo01.ProxyInvocationHandler;
import com.Gw.demo01.UserService;
import com.Gw.demo01.UserServiceImpl;

//使用動態代理
public class test {
    public static void main(String[] args) {
        
        //先new出需要代理的物件userService
        UserServiceImpl userService = new UserServiceImpl();
        
        //將userService放入動態代理器中,並獲取代理人proxy
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        proxyInvocationHandler.setTarget(userService);
        UserService proxy = (UserService) proxyInvocationHandler.getProxy();
        
        //通過代理人進行操作
        proxy.delete();
        proxy.add();
    }
}

8.AOP

提供宣告式事務;允許使用者自定義切面

使用Spring-AOP需要匯入依賴

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.9.1</version>
    <scope>runtime</scope>
</dependency>

1.一些術語的說明

  • 橫切關注點:跨越應用程式的多個模組的方法或功能,與業務邏輯無關,但需要關注的部分,如:日誌、安全、快取、事務等等
  • 切面(aspect):橫切關注點被模組化的特殊物件,如log類
  • 通知(advice):切面必須要完成的工作,也就是log類中的一個方法
  • 目標(target):被通知的物件
  • 代理(proxy):向目標物件應用通知後建立的物件
  • 切入點(pointCut):切面通知執行的地點
  • 連線點(joinPoint):與切入點匹配的執行點

2.Spring中AOP的三種實現方法

方法一:使用Spring中的API

public class log implements MethodBeforeAdvice {

    //method:要執行的方法
    //args:引數
    //target:目標物件
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" +method.getName() + "方法被執行了");
    }
}

public class afterLog implements AfterReturningAdvice {

    //returnValue:返回值

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("方法"+method.getName()+"的執行結果為"+returnValue);
    }
}

在xml中的配置

<!--方法一:未自定義切面-->

<!--配置AOP,需要匯入AOP的約束-->
<aop:config>
    <!--定義一個切入點,execution寫切入點位置,*代表任意位置-->
    <aop:pointcut id="pointcut" expression="execution(* com.Gw.demo01.UserServiceImpl.*(..))"/>

    <aop:advisor advice-ref="before" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="after" pointcut-ref="pointcut"/>
</aop:config>

方法二:自定義切面

public class diyAspect {

    public void before(){
        System.out.println("=========before=========");
    }

    public void after(){
        System.out.println("=========after==========");
    }

}

在xml中的配置

<!--方法二:自定義切面-->

<bean id="diyaspect" class="com.Gw.diy.diyAspect"/>

<aop:config>
    <!--自定義切面-->
    <aop:aspect ref="diyaspect">
        <!--設定切入點-->
        <aop:pointcut id="point" expression="execution(* com.Gw.demo01.UserServiceImpl.*(..))"/>
        <!--通知,可直接呼叫切面中的方法-->
        <aop:before method="before" pointcut-ref="point"/>
        <aop:after method="after" pointcut-ref="point"/>
    </aop:aspect>
</aop:config>

方法三:使用註解實現

package com.Gw;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect  //設定切面
public class Annotation {

    //設定切入點和通知
    @Before("execution(* com.Gw.demo01.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("=========before=========");
    }
    
    
    @After("execution(* com.Gw.demo01.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("=========after==========");
    }
    
    
    @Around("execution(* com.Gw.demo01.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("環繞前");
        Object proceed = jp.proceed();
        System.out.println("環繞後");
    }

}

9.整合Mybatis

用spring的配置取代mybatis-config.xml的配置,通常只在mybatis-config.xml中配置別名管理和設定

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<!--做別名管理和設定-->

    <typeAliases>
        <package name="com.Gw.pojo"/>
    </typeAliases>

</configuration>

匯入的依賴:

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.19</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.19</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.9.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.7</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>

方法一:直接實現

先建立一個mapper,在mapper.xml中實現方法,在原有的mybatis-config.xml的基礎上進行替換,配置的spring-dao.xml如下,將SqlSession利用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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    
    <!--DataSource:使用Sping的資料來源替代Mybatis的配置-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;userUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    
    
    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/Gw/Mapper/*.xml"/>
    </bean>

    
    <!--只能用構造器注入,因為template沒有set方法 -->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    
    <!--將實現類注入到Spring中-->
    <bean id="userMapper" class="com.Gw.Mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSessionTemplate"/>
    </bean>
    <bean id="userMapper2" class="com.Gw.Mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
    
    
</beans>

將sqlSession利用spring進行注入時,要求了一開始的mapper介面需要一個實現類,和sqlSession的set方法:

package com.Gw.Mapper;

import com.Gw.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper {

    //我們所有的操作現在都使用SqlSessionTemplate來執行
    private SqlSessionTemplate sqlSession;

    //spring注入要求必須有set方法
    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<User> selectUser() {
        return sqlSession.getMapper(UserMapper.class).selectUser();
    }

}

最後使用applicationContext.xml整合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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    
    <import resource="spring-dao.xml"/>
    <!--將實現類注入到Spring中-->
    <bean id="userMapper" class="com.Gw.Mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSessionTemplate"/>
    </bean>
</beans>

方法二:SqlSessionDaoSupport簡便實現

在一的配置的基礎上繼承SqlSessionDaoSupport,省去了建立sqlSession物件的麻煩,sqlSession物件直接由getSession()方法獲得,對應的mapper實現類如下:

package com.Gw.Mapper;

import com.Gw.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    
    //直接通過getSqlSession獲得物件
    @Override
    public List<User> selectUser() {
        SqlSession sqlSession = getSqlSession();
        return sqlSession.getMapper(UserMapper.class).selectUser();
    }

}

10.宣告式事務

把一組業務當做一個業務來開發,要麼都成功,要麼都失敗,確保完整性和一致性,spring 保證的是在不改變原有程式碼的基礎上進行事務注入,非常的nice

事務的ACID原則:

​ 原子性、一致性、隔離性、永續性

新增配置tx

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/context/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-aop.xsd">

要開啟spring 的事務管理功能需要在spring的配置檔案中建立一個DataSourceTransactionManager物件

<!--結合AOP實現事務的織入-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--給哪些方法配置事務-->
    <!--配置事務的七種傳播特性-->
    <tx:attributes>
        <tx:method name="selectUser" read-only="true"/>
        <tx:method name="add" propagation="REQUIRED"/>
        <tx:method name="delete"/>
        <tx:method name="update"/>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<!--配置事務切入點-->
<aop:config>
    <aop:pointcut id="txPointcut" expression="execution(* com.Gw.Mapper.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>