天天看點

SpringFramework-IOC(依賴注入)+AOP(面向切面程式設計)

SpringFramework-IOC(依賴注入)+AOP(面向切面程式設計)

文章目錄

    • 簡介
      • 七大子產品
    • IOC(控制反轉)
    • HelloSpring
    • IOC建立對象方式
    • Spring配置檔案
      • alias(别名)
      • Bean的配置
      • import
    • 依賴注入(DI)
      • set注入
      • c命名和p命名空間注入
    • bean的作用域
    • bean 的自動裝配(autowire)
    • 使用注解開發
      • bean(@Component)
      • 屬性注入(@Value(""))
      • 衍生的注解
      • 使用注解自動裝配(@Autowired)
      • 作用域
      • 使用Java的方式配置Spring
    • 代理模式
      • 靜态代理
      • 動态代理
    • AOP
      • 使用Spring的API接口實作
      • 自定義切入點類
      • 注解實作AOP(@Aspect)
    • 整合myBatis
      • 方法一
      • 方法二
    • 事務
      • 聲明式事務

簡介

中文文檔

Spring Framework中文文檔

  • 目的:解決企業應用開發的複雜性
  • 功能:使用基本的JavaBean代替EJB,并提供了更多的企業應用功能
  • 範圍:任何Java應用
  • Spring是一個輕量級控制反轉(IoC)和面向切面(AOP)的容器架構。
  • Rod Johnson是spring Framework的創始人
  • Spring的理念:使現在的技術更加的容易使用,整合現有的技術架構
  • SSH:Struct2 + Spring + Hibernate
  • SSM:SpringMvc + Spring +MyBatis
  • 優點:
    • Spring是一個開源的免費的架構
    • Spring是一個輕量級的、非入侵式的架構
    • 控制反轉(IOC),面向切面程式設計(AOP)
    • 支援事務的處理
    • 對架構的整合支援

      Spring就是一個輕量級的控制反轉(IOC)和面向切面程式設計(AOP)的架構

Github位址

maven倉庫:

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

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

七大子產品

SpringFramework-IOC(依賴注入)+AOP(面向切面程式設計)
  • Spring Boot:
    • 一個快速開發的腳手架
    • 基于SpringBoot可以快速的開發單個微服務
    • 約定大于配置
  • Spring Cloud:
    • 基于SpringBoot實作的

IOC(控制反轉)

  • 之前,程式主動建立對象,控制權在底層
  • 使用set注入,程式不再有主動權,變成了被動的接收對象,降低系統耦合性
  • 控制反轉是一種通過描述(XML或者注解)并通過第三方去生産或擷取特定對象的方式,在Spring中實作控制反轉的是IOC容器,其實作方法是依賴注入(Dependency Injection ,DI)
控制反轉IOC(Inversion of Control),是一種設計思想,沒有IoC的程式中,我們使用面向對象的程式設計,對象的建立與對象間的依賴關系完全寫死在程式中,對象的建立由程式自己控制,控制反轉後将對象的建立轉移給第三方

HelloSpring

  • 對象由Spring來建立,管理和裝配
  1. 建立一個測試類
public class Hello {
    private String str;
    public String getStr() {
        return str;
    }
    public void setStr(String str) {
        this.str = str;
    }
    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}
           
  1. 在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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
<!--使用Spring來建立對象,在Spring中這些都稱為bean
    類型 變量名 = new 類型();
    id:變量名
    class:new的對象
    property:相當于給對象裡的屬性設定值
        ref:引用Spring中建立好的對象
        value:基本的資料類型
-->
    <bean id="hello" class="com.huang.pojo.Hello">
        <property name="str" value="Spring"/>
    </bean>
</beans>
           
  1. 測試調用
public class myTest {
    @Test
    public void testHello(){
        //擷取Spring的容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //我們的對象都在Spring中管理了,要使用直接去取出來
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}
           

IOC建立對象方式

  • 在配置檔案加載的時候,容器中管理的對象就已經被建立了
  • 無參構造:property
  • 有參構造:constructor-arg
<bean id="hello" class="com.huang.pojo.Hello">
<!--無參構造-->
        <property name="str" value="Spring"/>
<!--有參構造方法:
        1. 下标指派
        2. 類型指派
        3. 直接通過參數名
-->
        <constructor-arg index="0" value="huang"/>
        <constructor-arg type="java.lang.String" value="yaohui"/>
        <constructor-arg name="str" value="hanhan"
    </bean>
           

Spring配置檔案

alias(别名)

  • 如果添加了别名,也可以通過别名擷取這個對象

Bean的配置

  • id:bean的唯一辨別符,也相當于我們學的對象名
  • class:bean對象所對應的全限定名
  • name:也是别名,可以起多個别名,可以用(,;空格)等來間隔
<bean id="myname" class="com.huang.pojo.Hello" name="name1 name2,name3">
    </bean>
           

import

  • 一般用于團隊開發,可以将多個配置檔案合并

依賴注入(DI)

  • 構造器注入
  • set方式注入
  • 拓展方式注入

set注入

  • 依賴注入:set注入
    • 依賴:bean對象的建立依賴于容器
    • 注入:bean對象中所有的屬性,由容器來注入
  • 包含類型:
bean | ref | idref | list | set | map | props | value | null
           
  • 例子:
<bean id="student" class="com.huang.pojo.Student">
        <!--1. 普通注入 value-->
        <property name="name" value="persistenthuang"/>

        <!--2. bean注入 ref-->
        <property name="hello" ref="hello"/>

        <!--3. 數組注入 array-->
        <property name="books">
            <array>
                <value type="java.lang.String">紅樓夢</value>
                <value type="java.lang.String">西遊記</value>
                <value type="java.lang.String">水浒傳</value>
                <value type="java.lang.String">三國演義</value>
            </array>
        </property>

        <!--4. List集合注入 list-->
        <property name="hobby">
            <list>
                <value type="java.lang.String">聽歌</value>
                <value type="java.lang.String">看電影</value>
            </list>
        </property>

        <!--5. Map注入 map-->
        <property name="card">
            <map>
                <entry key="cad1" value="123"/>
                <entry key="cad2" value="123456"/>
            </map>
        </property>

        <!--6. Set注入 set-->
        <property name="games">
            <set>
                <value type="java.lang.String">LoL</value>
                <value type="java.lang.String">紅警</value>
                <value type="java.lang.String">刀塔</value>
            </set>
        </property>

        <!--7. 空值注入 null-->
        <property name="wife">
            <null/>
        </property>

        <!--8. 配置注入:property-->
        <property name="properties">
            <props>
                <prop key="學号">22111222</prop>
                <prop key="班級">三年二班</prop>
                <prop key="姓名">persistenthuang</prop>
            </props>
        </property>
    </bean>
           

c命名和p命名空間注入

P命名空間:可以直接注入屬性的值(property)

  • 導入p命名空間
xmlns:p="http://www.springframework.org/schema/p"
           
  • 測試使用
//通過set注入
    <bean id="hello3" class="com.huang.pojo.Hello" p:str="huang">
    </bean>
           

C命名空間:

  • 引入C命名空間
xmlns:c="http://www.springframework.org/schema/c"
           
  • 測試使用
//通過構造器注入
    <bean id="hello4" class="com.huang.pojo.Hello" c:str="hhhh">
    </bean>
           
  • 注意:
    • p命名和c命名空間不能直接使用,要導入xml限制

bean的作用域

  • singleton(單例模式):Spring預設機制
  • prototype(原型模式):每次從容器中get的時候都會産生一個新對象
  • 其餘request、session、application,在web開發中才能用
範圍 使用 描述
singleton(單例) scope=“singleton” (預設)為每個 Spring IoC 容器的單個 object 執行個體定義單個 bean 定義。
prototype(原型) scope=“prototype” 為任意數量的 object 執行個體定義單個 bean 定義。
request(請求) scope=“request” 将單個 bean 定義範圍限定為單個 HTTP 請求的生命周期。也就是說,每個 HTTP 請求都有自己的 bean 執行個體,該執行個體是在單個 bean 定義的後面建立的。僅在 web-aware Spring ApplicationContext的 context 中有效。
session scope=“session” 将單個 bean 定義範圍限定為 HTTP Session的生命周期。僅在 web-aware Spring ApplicationContext的 context 中有效。
application(應用) 将單個 bean 定義範圍限定為ServletContext的生命周期。僅在 web-aware Spring ApplicationContext的 context 中有效。
WebSocket 将單個 bean 定義範圍限定為WebSocket的生命周期。僅在 web-aware Spring ApplicationContext的 context 中有效。

bean 的自動裝配(autowire)

  • 自動裝配式Spring滿足bean依賴的一種方式
  • Spring會在上下文中自動查找,并自動給bean裝配屬性
  • Spring中的三種裝配的方式:
    • 在xml中顯示的配置
    • 在java中顯示配置
    • 隐式的自動裝配bean
  • 裝配方式:
    • byName:(名字對應)會自動在容器上下文中查找,和自己對象set方法後面的值對應的beanid
    • byType:(類型唯一)會自動在容器上下文中查找,和自己對象屬性類型相同的bean

使用注解開發

  • 在使用Spring4之後,要使用注解開發,必須保證aop包導入了
  • 使用注解要導入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">

    <context:annotation-config/>
<!--指定要掃描的包,這個包下的注解就會生效-->
    <context:component-scan base-package="com.huang.pojo"/>
</beans>
           

bean(@Component)

  • 加注解:@Component
  • @Component:元件,放在類上,說明這個類被Spring管理了,就是bean

屬性注入(@Value(""))

  • 加注解:@Value("")
  • 可以放在屬性或者set方法上
  • 适用簡單屬性,複雜屬性适用xml注入

衍生的注解

  • 【@Component】有幾個衍生注解,在Web開發中,會按照mvc三層架構分層
    • Dao:【@Repository】
    • Service:【@Service】
    • Controller:【@Controller】
  • 這四個注解功能都一樣 ,代表将這個類注冊到Spring中,裝配Bean

使用注解自動裝配(@Autowired)

  • jdk1.5支援注解,Spring2.5就支援注解了
  • 使用注解:
    • 導入限制: xmlns:context=“http://www.springframework.org/schema/context”
    • 配置注解支援:context:annotation-config/
    • 在要自動裝配的屬性上使用,也可以在Set方法上使用: @Autowired
<?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">
    <!--指定要掃描的包,這個包下的注解就會生效-->
    <context:component-scan base-package="com.huang.Dao"/>
    <context:annotation-config/>
</beans>
           
  • 使用Autowired我們可以不用編寫Set方法,前提是你這個自動裝配的屬性在IOC(Spring)容器中存在,且符合名字byName
    • 顯示的定義了@Autowired(required = false),說明這個對象可以為空,否則不允許為空
    • @Nullable:字段标記了這個注解,說明這個注解可以為NULL
    • @Qualifier(value=“指定的命名”):自動裝配環境比較複雜的時候,無法通過一個注解完成時添加的
    • 不使用Autowired時可以使用@Resource(name="")
@Autowired(required = false)
    @Qualifier(value = "hello2")
    private Hello hello;    
           
  • @Autowired和@Resource的差別
    • 都是用來自動裝配的,都可以放在屬性字段上
    • @Autowired通過byType的方式實作,而且必須要求這個對象存在
    • @Resource預設通過byName方式實作,如果找不到名字,則通過byType實作

作用域

  • @Scope(“singleton”):單例模式
  • @Scope(“prototype”):原型模式
  • XML與注解
    • xml:更加萬能,适用于任何場合,維護簡單友善
    • 注解:不是自己的類适用不了,維護相對複雜
    • xml與注解結合:
      • xml用來管理bean
      • 注解完成屬性注入

使用Java的方式配置Spring

  • 不适用Spring的xml配置
  • JavaConfig是Spring的一個子項目,Spring4之後變成了核心功能
  1. 寫一個實體類
//@Component:等價于<bean id="user" class="com.huang.Dao.User"/>
@Data
@Component
@Scope("singleton")
public class User {
    @Value("huang")
    private String name;
}
           
  1. 寫一個 配置類
//這個也會Spring容器托管,注冊到容器中,因為它本身就是一個元件
//@Configuration代表一個配置類,和之前的beans.xml一樣
@Configuration
@ComponentScan("com.huang") //掃描包
@Import(config2.class)      //引入其他配置類
public class huangConfig {
    /**
     * 注冊一個bean相當于之前寫的一個bean标簽
     * 方法名 = bean标簽中的id屬性
     * 方法傳回類型 = bean标簽中的class屬性
     */
    @Bean
    public User getUser(){
        return new User();
    }
}
           
  1. 調用測試
@Test
    public void testHello(){
        //如果完全使用配置類的方式去做
        //隻能通過AnnotationConfig上下文來擷取容器
        //通過配置類的class對象來加載
        ApplicationContext context = new AnnotationConfigApplicationContext(huangConfig.class);
        User user = context.getBean("getUser", User.class);
        System.out.println(user.toString());
    }
           

代理模式

SpringFramework-IOC(依賴注入)+AOP(面向切面程式設計)
  • 分類:
    • 靜态代理
    • 動态代理

靜态代理

  • 角色
    • 抽象角色:一般會使用接口或者抽象類來解決
    • 真實角色:被代理的角色
    • 代理角色:代理真實角色,代理真實角色後,一般會做一些附屬操作
    • 客戶角色:通路代理對象的人
  • 代理模式的好處:
    • 可以使用真實角色的操作更加純粹,不用去關注一些公共業務
    • 公共業務也就交給了代理角色!實作了業務的分工
    • 公共業務發生擴充的時候,友善集中管理
  • 缺點:
    • 一個真實角色就會産生一個代理角色,代碼量會翻倍,開發效率會變低
    • 動态代理好處:
      • 一個動态代理代理的是一類接口,一般就是對應的一類業務
      • 一個動态代理可以代理多個類,隻要實作了同一個接口即可

動态代理

  • 角色:動态代理和靜态代理的角色是一樣
  • 動态代理的代理類是動态生成的
  • 動态代理分為兩大類:基于接口的動态代理,基于類的動态代理
    • 基于接口:JDK動态代理
    • 基于類:cgLib
    • Java位元組碼實作:javasist
  • 了解兩個類:
    • Proxy:代理
    • InvocationHandler:調用處理程式

InvocationHandler是由代理執行個體的調用處理程式實作的接口。

每個代理執行個體都有一個關聯的調用處理程式。 在代理執行個體上調用方法時,方法調用将被編碼并排程到其調用處理程式的invoke方法。

  • 實作一個萬能代理類生成類:
//使用這個類自動生成代理類
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }
    //生成代理對象
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }
    //處理代理實類,并傳回結果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //動态代理的本質,就是使用反射機制實作
        Object result = method.invoke(target, args);
        return result;
    }
}
           
  • 測試使用:Host是一個繼承Rent接口的實作類,Rent是一個
public class Client {
    public static void main(String[] args) {
        //真實角色
        Host host=new Host();
        //代理角色:動态建立
        ProxyInvocationHandler handler = new ProxyInvocationHandler();
        //通過調用程式處理角色,來建立對象
        handler.setTarget(host);
        Rent proxy = (Rent)handler.getProxy();  //這裡的proxy是動态生成的
        proxy.rent();
    }
}
           

AOP

AOP(Aspect Oriented Programming)意為:面向切面程式設計,通過預編譯方式和運作期間動态代理實作程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring架構中的一個重要内容,是函數式程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,進而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
  • 添加依賴
<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
           

提供聲明式事務:允許使用者自定義切面

  • 橫切關注點:跨越應用程式多個子產品的方法或功能。即是,與我們業務邏輯無關,但是我們需要關注的部分,就是橫切關注點。如日志,安全,緩存,事務等等
  • 切面(ASPECT):橫切關注點,被子產品化的特殊對象。即,它是一個類
  • 通知(Advice):切面必須要完成的工作。即,它是類中的一個方法
  • 目标(Target):被通知對象
  • 代理(Proxy):向目标對象應用通知後建立的對象
  • 切入點(PointCut):切面通知執行的“地點”的定義
  • 連接配接點(JointPoint):與切入點比對的執行點
    SpringFramework-IOC(依賴注入)+AOP(面向切面程式設計)

使用Spring的API接口實作

  • 建立兩個日志類繼承接口:MethodBeforeAdvice,AfterReturningAdvice
public class logBefore implements MethodBeforeAdvice {
    /**
     * method:要執行的目标對象的方法
     * objects:參數
     * o:目标對象
     */
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被執行了");
    }
}

public class logAfter implements AfterReturningAdvice {
    //o:傳回值
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("執行了"+method.getName());
    }
}
           
  • 在Spring的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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--注冊bean-->
    <bean id="host" class="com.Proxy.Host"/>
    <bean id="logbefore" class="com.Proxy.Log.logBefore"/>
    <bean id="logafter" class="com.Proxy.Log.logAfter"/>
    
    <!--方式一:使用原生态Spring API接口-->
    <!--配置AOP:需要導入aop的限制-->
    <aop:config>
        <!--切入點: expression表達式,execution(要執行的位置)-->
        <aop:pointcut id="pointCut" expression="execution(* com.Proxy.Host.*(..))"/>
        <!--執行環繞增加-->
        <aop:advisor advice-ref="logbefore" pointcut-ref="pointCut"/>
        <aop:advisor advice-ref="logafter" pointcut-ref="pointCut"/>
    </aop:config>
</beans>
           
  • 測試調用
@Test
    public void testAOP(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Rent host = (Rent) context.getBean("host");
        host.rent();
    }
           

自定義切入點類

execution用法參考連接配接

  • 自定義一個類
public class DiyPointCut {
    private  void before(){
        System.out.println("===============before=============");
    }
    private  void after(){
        System.out.println("===============after=============");
    }
}
           
  • 編寫配置檔案
<!--方式二:自定義類-->
    <bean id="diy" class="com.Proxy.Diy.DiyPointCut"/>
    <aop:config>
        <!--自定義切面:ref要引用的類-->
        <aop:aspect ref="diy">
            <!--切入點-->
            <aop:pointcut id="point" expression="execution(* com.Proxy.Host.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
           

注解實作AOP(@Aspect)

  • 代理方法寫法:
@Aspect
public class DiyPointCut {

    @Before("execution(* com.Proxy.Host.*(..))")
    private  void before(){
        System.out.println("===============before=============");
    }

    @After("execution(* com.Proxy.Host.*(..))")
    private  void after(){
        System.out.println("===============after=============");
    }

    //在環繞增強中,可以給一個參數,代表我們要擷取處理切入的點
    @Around("execution(* com.Proxy.Host.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("===============around-before=============");
        Object proceed = jp.proceed();  //代表執行方法
        System.out.println("===============around-after=============");
    }
}
           
  • 注冊方法
<!--方式三-->
    <bean id="diy" class="com.Proxy.Diy.DiyPointCut"/>
    <!--開啟注解支援, JDK(預設proxy-target-class="false") cgLib(proxy-target-class="true")-->
    <aop:aspectj-autoproxy/>
           

整合myBatis

官方文檔

  1. 導入相關jar包
    • junit
    • myBatis
    • mysql資料庫
    • Spring
    • aop
    • myBatis-spring
<dependencies>
        <!--單元測試-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!--mysql連接配接資料庫-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

        <!--mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>

        <!--spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <!--spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

        <!--mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>
    </dependencies>
           
  1. 編寫資料源
  2. sqlSessionFactory
  3. sqlSessionTemplate
  4. 給接口加實作類
  5. 将自己寫的實作類注入到mybatis
  6. 測試

方法一

  • 實體類:
@Data
public class User {
    int id;
    String class_name;
}
           
  • Mapper接口
public interface UserMapper {
    public List<User> selectUser();
}
           
  • mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=命名空間-->
<mapper namespace="com.huang.mapper.UserMapper">
    <select id="selectUser" resultType="com.huang.pojo.User">
            select * from school.test2
        </select>
</mapper>
           
  • mapper的實作類
@Data
public class UserMapperImpl implements UserMapper {

    SqlSessionTemplate sqlSession;
    public List<User> selectUser() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();
    }
}
           
  • myBatis-config.xml:mybatis的核心配置檔案
<?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核心配置檔案-->
<configuration>
</configuration>
           
  • spring-dao.xml:整合配置檔案,專注于mybatis的一些對象生成
<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

<!--DataSource:使用spring的資料源替換mybatis的配置,使用spring提供的jdbc-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/school?useSSL=false&amp;useUnicode=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"/>
        <!--綁定myBatis-->
        <property name="configLocation" value="classpath:myBatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/huang/mapper/UserMapper.xml"/>
    </bean>

<!--SqlSessionTemplate就是我們用的sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--隻能使用構造器注入,因為沒有set函數-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

</beans>
           
  • applicationContext.xml:總配置檔案,引入spring-dao.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <import resource="spring-dao.xml"/>
    <bean id="userMapper" class="com.huang.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
    
    <bean id="userMapper2" class="com.huang.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>
           
  • 測試調用
@Test
    public void testSB(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        for (User user : userMapper.selectUser()) {
            System.out.println(user.toString());
        }
    }
           

方法二

  • 不用建立sqlsession對象了,實作接口繼承一個SqlSessionDaoSupport對象
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
    public List<User> selectUser() {
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}

           
  • 注冊
<bean id="userMapper2" class="com.huang.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
           

事務

  • 事務:
  • 要麼都成功,要麼都失敗
  • 保持完整性和一緻性
  • 事務的ACID原則:原子性,一緻性,隔離性,持久性

聲明式事務

  • 使用AOP的方式
  • 修改後的spring-dao.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: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/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">

<!--DataSource:使用spring的資料源替換mybatis的配置,使用spring提供的jdbc-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/school?useSSL=false&amp;useUnicode=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"/>
        <!--綁定myBatis-->
        <property name="configLocation" value="classpath:myBatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/huang/mapper/UserMapper.xml"/>
    </bean>

<!--SqlSessionTemplate就是我們用的sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--隻能使用構造器注入,因為沒有set函數-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

<!--配置聲明式事務-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--結合AOP實作事務的織入-->
    <!--配置事務的通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--給哪些方法配置事務-->
        <!--配置事務傳播特性-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

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

</beans>