详解Spring

Spring

1.本章学习内容

1.Spring框架概要

2.IOC容器

3.AOP

4.jdbcTemplate

5.事务管理

6.Spring5新特性

7.Spring整合MyBatis

2.Spring概要

**概述:**它是轻量级的开源的JavaEE框架

  • 轻量级:他的体积小,依赖的jar包比较少,并且不需要额外依赖其他的组件

  • 开源:免费提供源代码

  • 框架:可以简化我们构建软件的过程

**目的:**为了解决企业级应用的复杂性

核心:

  • IOC:控制反转- 把创建对象的过程交给Spring进行管理
  • AOP:面向切面编程 - 不修改源码进行功能增强

优点:

  • 方便解耦,简化开发

  • 对AOP编程的支持

  • 方便程序的测试

  • 方便整合其他各种的框架

  • 方便进行事务操作

  • 降低API开发

3.入门案例

4.IOC容器

概述:

  • 控制反转

  • 综上所述:控制反转就是 把创建对象,和对象的调用的过程交给Spring来管理 。目的是为了降低类与类之间的耦合性。

底层原理:

  • XML解析

  • 工厂模式

  • 反射

原理图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EYaHb63p-1617528150776)(D:\图片\IOC.png)]

重要概念:

  1. IOC 容器:IOC的实现,依赖于IOC容器,而IOC容器的本质就是对象工厂

  2. IOC容器的实现:

    • BeanFactory:是最底层的接口,他只提供了最简单的容器功能:加载配置文件 和 创建对象

      • 当加载配置文件时,不会创建被配置的对象,只有在使用时,对象才会创建。
        • 好处:节省内存
        • 坏处:因为在服务器运行的时候去创建对象,会影响执行效率
    • ApplicationContext:应用上下文,它是继承了BeanFactory。它是Spring更高级的一个容器接口,他提供了更多有用的功能

      • 当配置文件的时候,会同时创建被创建配置的对象
        • 好处:效率高,将复杂的创建过程在服务器启动时完成
        • 坏处:耗费资源

3.ApplicationContext的两个实现类

  • ClassPathXmlApplicationContext:从项目中的resources文件中加载配置文件

  • FileSystemXmlApplicationContext:从文件系统读取配置文件(需要访问权限)

  • AnnotionConfigApplicationContext:读取注解配置

5.IOC操作 - Bean管理

概念:IOC操作 - Bean管理是指两个操作: 1.Spring创建对象 2.Spring注入属性(属性赋值)

实现方式:

​ 1.XML方式

​ 2.注解方式

5.1基于XML方式-创建对象

该方式与入门案列方式相同

bean标签中常用属性

  • id:唯一标识,通过该属性可以找到对应的Bean标签
  • class:类的全限定类名

注意事项

​ 创建对象时,默认执行无参构造方法来完成对象的创建(反射)

5.2基于XML方式-注入属性

**DI:**依赖注入,它是IOC的一个具体操作

分类

  1. 使用Set方法进行注入
  2. 使用构造器方式经行注入

演示:

1.实体类

public class Book {
    private String name;
    private String author;

    public Book(String name, String author) {
        this.name = name;
        this.author = author;
    }

    public Book() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }
}

2.配置XML文件

Set方法

​ 属性注入通过<property>

name:实体类属性名

value:属性值

<?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">
    <!-- 创建User对象-->
    <bean id="book" class="com.wdzl.pojo.Book">
        <property name="name" value="Java从入门到入土"></property>
        <property name="author" value="詹姆士"></property>
    </bean>
</beans>

构造器方法

​ 属性注入通过<constructor-arg>

name:实体类属性名 index:通过索引

value:属性值

<?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">
    <!-- 创建User对象-->
    <bean id="book" class="com.wdzl.pojo.Book">
<!--        <constructor-arg name="name" value="Java高级数"></constructor-arg>-->
<!--        <constructor-arg name="author" value="赵子龙"></constructor-arg>-->
        <constructor-arg index="0" value="Java高级数"></constructor-arg>
        <constructor-arg index="1" value="赵子龙"></constructor-arg>
    </bean>
</beans>

P命名空间注入

xmlns:p="http://www.springframework.org/schema/p" 引入约束

<bean id="book" class="com.wdzl.pojo.Book" p:name="Java入门宝典" p:author="詹姆士·赵大帅哥"></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"
       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">
    <!-- P命名空间注入-->
    <bean id="book" class="com.wdzl.pojo.Book" p:name="Java入门宝典" p:author="詹姆士·赵大帅哥"></bean>


</beans>

3.测试

public class BookTest {
    @Test
    public void Test(){
        //1.加载配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans2.xml");
        Book book = context.getBean("book", Book.class);
        System.out.println(book);
    }
}

特殊符号注入

​ 1.null

<constructor-arg name="name" >
           <null></null>
       </constructor-arg>

​ 2.转义字符

<constructor-arg name="author" >
 <value>"&lt;关羽&gt;"</value>
    </constructor-arg>

​ 3.CDATA

<constructor-arg name="author" >
           <value><![CDATA[<詹姆斯·屈波>]]></value>
       </constructor-arg>

外部Bean

1.新建Moule,在pom.xml中添加依赖

2.按照三层架构成绩:Dao,Service,Web,在dao层中添加方法,在Service层中添加对Dao层的依赖(dao成员变量,对应的set方法)

3.配置对象信息

<?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">
<!-- 创建userDao对象-->
    <bean id="userDao" class="com.wdzl.dao.impl.UserDaoImpl">

    </bean>
    <!--        创建UserService对象-->
    <bean id="userService" class="com.wdzl.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>

内部类

1.再上一个演示案例的基础上,创建两个实体类Emp和Dept,其中Emp包含Dept对象属性

2.配置对象信息

<?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">
<!--内部Bean-->
    <bean id="emp" class="com.wdzl.pojo.Emp">
<!--        基本数据类型-->
        <property name="name" value="赵童"></property>
        <property name="gender" value=""></property>
<!--        引用数据类型-->
        <property name="dept">
            <bean id="dept" class="com.wdzl.pojo.Dept">
                <property name="deptName" value="研发部"></property>
            </bean>

        </property>
    </bean>
</beans>

级联操作

1.方式一

<?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">
    
<!--级联操作1-->
    <bean id="dept" class="com.wdzl.pojo.Dept">
        <property name="deptName" value="运营部"></property>
    </bean>
    <bean id="emp" class="com.wdzl.pojo.Emp">
        <!--        基本数据类型-->
        <property name="name" value="赵童"></property>
        <property name="gender" value=""></property>
        <!--        引用数据类型-->
        <property name="dept" ref="dept"></property>

    </bean>

</beans>

2.方式二

<?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">
    <bean id="dept" class="com.wdzl.pojo.Dept">

    </bean>
    <bean id="emp" class="com.wdzl.pojo.Emp">
<!--        基本数据类型-->
        <property name="name" value="赵童"></property>
        <property name="gender" value=""></property>
<!--        引用数据类型-->
        <property name="dept" ref="dept"></property>
        <property name="dept.deptName" value="运营部"></property>
    </bean>
</beans>

注意事项:

​ 针对方式2: - -定要提供get. set方法,否则配置文件中的某些属性就会报红。

(基本数据类型)数组,集合属性的注入

1.创建一个实体类

package com.wdzl.pojo;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class Demo {
    private String[] string;
    private List<String> list;
    private Map<String ,String> map;

    @Override
    public String toString() {
        return "Demo{" +
                "string=" + Arrays.toString(string) +
                ", list=" + list +
                ", map=" + map +
                '}';
    }

    public String[] getString() {
        return string;
    }

    public void setString(String[] string) {
        this.string = string;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public Map<String, String> getMap() {
        return map;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public Demo(String[] string, List<String> list, Map<String, String> map) {
        this.string = string;
        this.list = list;
        this.map = map;
    }

    public Demo() {
    }
}

2.配置对象属性

<?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">
   <bean id="demo" class="com.wdzl.pojo.Demo">
       <!-- 字符串数组-->
       <property name="strings">
           <array>
               <value>你好</value>
               <value>小老弟</value>
           </array>
       </property>
       <!-- list集合-->
       <property name="list">
           <list>
               <value>hello</value>
               <value>people</value>
           </list>
       </property>
       <!-- map集合-->
       <property name="map">
           <map>
               <entry key="你好" value="世界"></entry>
               <entry key="哈哈" value="屈波"></entry>
               <entry key="" value="唐康"></entry>
           </map>
       </property>
   </bean>

</beans>
  • 引用数据类型

城市类:

package com.wdzl.pojo;

public class City {
    private String cityName;

    @Override
    public String toString() {
        return "City{" +
                "cityName='" + cityName + '\'' +
                '}';
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    public City(String cityName) {
        this.cityName = cityName;
    }

    public City() {
    }
}

省类:

package com.wdzl.pojo;

import java.util.List;

public class Province {
    private List<String> cities;

    @Override
    public String toString() {
        return "Province{" +
                "cities=" + cities +
                '}';
    }

    public List<String> getCities() {
        return cities;
    }

    public void setCities(List<String> cities) {
        this.cities = cities;
    }

    public Province(List<String> cities) {
        this.cities = cities;
    }

    public Province() {
    }
}

2.配置对象信息

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util
                           https://www.springframework.org/schema/util/spring-util.xsd">
    <util:list id="cityList">
        <value>西安</value>
        <value>宝鸡</value>
        <value>延安</value>
    </util:list>
    <bean id="province" class="com.wdzl.pojo.Province">
        <property name="cities" ref="cityList"></property>
    </bean>


<!--    <bean id="city" class="com.wdzl.pojo.City">-->
<!--        <property name="cityName" value="西安"></property>-->
<!--    </bean>-->

<!--    <bean id="city2" class="com.wdzl.pojo.City">-->
<!--        <property name="cityName" value="宝鸡"></property>-->
<!--    </bean>-->
<!--    <bean id="city3" class="com.wdzl.pojo.City">-->
<!--        <property name="cityName" value="安康"></property>-->
<!--    </bean>-->
<!--    <bean id="city4" class="com.wdzl.pojo.City">-->
<!--        <property name="cityName" value="延安"></property>-->
<!--    </bean>-->

<!--   <bean id="province" class="com.wdzl.pojo.Province">-->
<!--       <property name="cities">-->
<!--           <list>-->
<!--               <ref bean="city"></ref>-->
<!--               <ref bean="city2"></ref>-->
<!--               <ref bean="city3"></ref>-->
<!--               <ref bean="city4"></ref>-->
<!--           </list>-->
<!--       </property>-->
<!--   </bean>-->

</beans>

FactoryBean:

**概述:**Spring中有两种类型的Bean,一种是普通Bean,一种是工厂Bean

  • 普通Bean:在配置文件中定义的Bean类型就是返回类型。
  • 工厂Bean:在配置文件中配置bean类型与返回类型不同。

演示:

创建一个工厂类

/**
 * 工厂Bean类型
 */
public class MyBean implements FactoryBean<String> {
    /**
     * 获取对象:此方法中定义了注入MyBean时,真正返回的对象
     * @return
     * @throws Exception
     */
    @Override
    public String getObject() throws Exception {
        return "我是钢铁侠";
    }

    /**
     * 返回对象类型
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return null;
    }

    /**
     * 是否是单例
     * @return
     */
    @Override
    public boolean isSingleton() {
        return false;
    }


}

配置对象信息

<?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">
    <bean id="myBean" class="com.wdzl.pojo.MyBean"></bean>
</beans>

测试案例

  @Test
    public void factoryBeanTest(){
        ApplicationContext context=new ClassPathXmlApplicationContext("bean6.xml");
       String province = (String)context.getBean("myBean",String.class);
        System.out.println(province);
    }

5.3 Bean的作用域

**概述:**在Spring中,设置创建Bean实例是单例还是多例。默认情况,Bean是单例。

注意

Singletonprototype 的区别:

  1. Singleton :在加载配置文件时,对象便会创建,并且,只创建一个对象
  2. prototype :在加载配置文件时,并不会创建对象,在调用getBean方法时,才会创建对象,并且每次调用都会创建。

5.4 Bean的生命周期

概述:

​ 一个对象从创建到销毁的过程

过程:

  1. 通过构造器创建Bean实例
  2. 为Bean的属性设置值或引用其他Bean(调用set)
  3. 调用Bean初始化方法
  4. Bean对象获取
  5. 容器关闭,调用销毁Bean的方法

演示

实体类

public class User {
    private String name;

    public User(){
        System.out.println("第一步:通过构造器创建对象");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("第二步,为Bean属性设置值");
        this.name = name;
    }
    public void init(){
        System.out.println("第三步:调用Bean初始化方法");
    }

    public void destroy(){
        System.out.println("第五步:调用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
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.wdzl.pojo.User" init-method="init" destroy-method="destroy">
        <property name="name" value="周星驰"></property>
    </bean>
<!--    <bean id="myBeanLast" class="com.wdzl.pojo.MyBeanLast"></bean>-->

</beans>

结果

第一步,通过构造器创建对象
第二步,为Bean属性设值
第三步,调用初始化方法
第四步:Bean的对象获取
第五步,调用摧毁方法

在Bean的生命周期中,如果配置了后置处理,生命周期会额外增加两步

  1. ​ 通过构造器创建Bean实例
  2. 为Bean的属性设置值或引用其他Bean(调用set)
  3. 执行后置处理
  4. 调用Bean初始化方法
  5. 执行后置处理
  6. Bean对象获取
  7. 容器关闭,调用销毁Bean的方法

演示

​ 在上述演示中再加入一个实体类

/**
 * 后置处理类
 */
public class MyBeanLast implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第三步:执行后置处理+postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第五步:执行后置处理+postProcessAfterInitialization");
        return 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
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.wdzl.pojo.User" init-method="init" destroy-method="destroy">
        <property name="name" value="周星驰"></property>
    </bean>
    <bean id="myBeanLast" class="com.wdzl.pojo.MyBeanLast"></bean>

</beans>

结果

第一步,通过构造器创建对象
第二步,为Bean属性设值
执行后置处理:postProcessBeforeInitialization
第三步,调用初始化方法
执行后置处理:postProcessAfterInitialization
第四步:Bean的对象获取
第五步,调用摧毁方法

5.5 XML方式-自动装配

概述:

​ 根据指定的装配规则(属性名称,属性类型),Spring自动将匹配的属性经行注入

实现:

​ 借助<bean> 标签里的autowrie属性来实现自定装配,该属性有两个值

  • byName:根据属性名称注入
  • byType:根据属性类型注入

注意

  • byType:如果有多个class属性相同的bean标签,自动装配会报错

5.6 引入外部标签

<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:property-placeholder location="jdbc.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driverClassName}"></property>
        <property name="url" value="${druid.url}"></property>
        <property name="username" value="${druid.username}"></property>
        <property name="password" value="${druid.password}"></property>
    </bean>


    <!-- 直接方式:配置连接信息-->
<!--    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">-->
<!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>-->
<!--        <property name="url" value="jdbc:mysql:///test"></property>-->
<!--        <property name="username" value="root"></property>-->
<!--        <property name="password" value="13992794421"></property>-->
<!--    </bean>-->

5.7基于注解方式-创建对象

**注解概述:**注解是代码的特殊标记

注解格式:@注解名称(属性名=属性值,属性名2=属性值2。。。。)

**注解应用:**它可以简化XML的配置,注解可以用在类上,属性上,方法上。

Spring针对创建对象提供了4个注解

  • @Component:普通类使用
  • @Service:Service层使用
  • @Controller:Web层使@
  • @Repository:Dao层使用

这四个注解功能是相同的,都可以用来创建Bean实例。

1.新建Model,添加依赖

2.创建Dao层实体类,在该类上添加注解

@Repository(value = "userDao")//相当于配置文件中Bean id属性
public class UserDao {
    public void addUser(){
        System.out.println("UserDao:addUser....");
    }
}

3.在配置文件中开启注解扫描

<?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
">
<!-- 直接方式配置连接信息-->
    <!-- 直接方式:配置连接信息-->
    <!--    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">-->
    <!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>-->
    <!--        <property name="url" value="jdbc:mysql:///test"></property>-->
    <!--        <property name="username" value="root"></property>-->
    <!--        <property name="password" value="13992794421"></property>-->
    <!--    </bean>-->

<!--    引用外部配置-->
    <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driverClassName}"></property>
        <property name="url" value="${druid.url}"></property>
        <property name="username" value="${druid.username}"></property>
        <property name="password" value="${druid.password}"></property>
    </bean>





<bean id="emp" class="com.wdzl.pojo.Emp" autowire="byName"></bean>
    <bean id="dept" class="com.wdzl.pojo.Dept">
        <property name="name" value="研发部"></property>
    </bean>
</beans>

测试

import com.wdzl.pojo.Emp;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AutowireTest {
    @Test
    public void test(){
        ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
        Emp emp = context.getBean("emp", Emp.class);
        System.out.println(emp);
    }
}

5.8基于注解方式-属性注入

常用注解:

​ 1.@AutoWired:根据属性类型进行自动重装载

​ 2.@Qualifier :根据属性名进行注入

​ 3.@Resource:根据类型注入,也可以根据名称注入

​ 4.@Value:基本数据类型的注入

演示:

@AutoWired

@Qualifier

  • 要与@AutoWired同时使用
  • 同时使用的目的是为了解决根据属性类型无法自动

@Resource

@Value

6.AOP

概述:

​ 面向切面编程-在不改变源码的情况下,对现有程序功能进行维护。

6.1AOP底层原理

概述:底层实用了动态代理技术

分类:两种情况的动态代理

  • 有接口的情况:使用了JDK的动态代理
    • 代理对象与被代理对象实现相同的接口
  • 没有接口的情况,使用了CGLIB动态代理
    • 通过创建子类对象,在子类中重写方法,并通过super.方法名()调用被代理类中的方法

6.2AOP相关术语

  • 连接点(JoinPoint):类里面那些方法可以被增强,这些方法就叫做连接点
  • 切入点(PoinCut):类中实际被增强的方法,称为切入点
  • 通知/增强(Advice):被增强的方法中增强部分的代码称为通知或者增强
    • 前置增强:在调用被增强方法前执行
    • 后置增强:在调用被增强方法后执行
    • 环绕增强:在调用被增强方法前后都执行
    • 异常增强:在调用被增强方法出现异常时增强
    • 最终增强:在调用被增强方法后,无论是否出现异常,都会被执行
  • 切面(Aspect):切面本身是一个动作,将增强应用到切入点的过程
  • 代理(Proxy)
  • 目标对象(Target)
  • 织入(Weaving)

6.3AspectJ

概述:

​ AspectJ时一个独立的AOP框架,一般开发中将AspectJ 与Spring框架-起使用,进行AOP操作

实现AOP的两种方式:

​ 1.基于XML方式实现

2.基于注解方式实现

相关依赖:

<dependencies>
<!--    Spring依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>
<!-- 日志依赖-->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.1</version>
    </dependency>
<!-- 测试依赖-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

<!-- aspectJ依赖-->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.6</version>
    </dependency>

    <dependency>
        <groupId>aopalliance</groupId>
        <artifactId>aopalliance</artifactId>
        <version>1.0</version>
    </dependency>

    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>
</dependencies>

切入点表达式

**概述:**让Spring框架知道哪个类里面的那个方法需要增强

语法结构:

  • execution([权限修饰符] [返回值类型] [全限定类名] .[方法名]([参数列表]))

    • 权限修饰符 可以省略
    • 返回值*代表任意返回值类型
  • 举例

    • 对com.wdzl.dao.UserDao类中的addUser方法进行增强

    execution(* com.wdzl.dao.UserDao.addUser(…))

1.新建Module,添加依赖

2.按照三层架构创建包结构

3.编写dao层接口

package com.wdzl.dao;

public interface UserDao {
    void addUser();
}

4.实现dao层接口的方法

package com.wdzl.dao.Impl;

import com.wdzl.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public void addUser() {
        System.out.println(3/0);
        System.out.println("天不生我李志刚");
    }
}

5.产生代理对象

package com.wdzl.proxy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect//将该类生产代理对象
public class UserDaoProxy {
    /**
     * 前置增强
     */
    @Before(value = "execution(* com.wdzl.dao.Impl.UserDaoImpl.addUser(..))")
    public void before(){
        System.out.println("before:前置增强.....");
    }



    /**
     * 最终增强
     */
    @After(value = "execution(* com.wdzl.dao.Impl.UserDaoImpl.addUser(..))")
    public void after(){
        System.out.println("after:最终增强...");
    }

    /**
     * 后置增强
     */
    @AfterReturning(value ="execution(* com.wdzl.dao.Impl.UserDaoImpl.addUser(..))")
    public void afterReturning(){
        System.out.println("AfterReturning:后置增强...");
    }

    /**
     * 异常增强
     */
    @AfterThrowing(value ="execution(* com.wdzl.dao.Impl.UserDaoImpl.addUser(..))")
    public void afterThrowing(){
        System.out.println("AfterThrowing:异常增强...");
    }

    /**
     * 环绕增强
     */
    @Around(value = "execution(* com.wdzl.dao.Impl.UserDaoImpl.addUser(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕之前...");
        joinPoint.proceed();
        System.out.println("环绕之后...");
    }
}

6.编写配置文件

<?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"
       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"
>
<!-- 开启组件扫描-->
    <context:component-scan base-package="com.wdzl"></context:component-scan>


    <!--生成Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>



</beans>

7。测试

import com.wdzl.dao.Impl.UserDaoImpl;
import com.wdzl.dao.UserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopTest {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        UserDao userDaoImpl = context.getBean("userDaoImpl", UserDao.class);
        userDaoImpl.addUser();

    }
}

7.JDBCTemplate

概述:

​ Spring对JDBC的封装,使用可以方便的去操作数据库

对用户进行增删改查

1.新建Module添加相关依赖

2.按照三层架构创建包结构

3.创建Student实体类

package com.wdzl.pojo;

/**
 * 学生类
 */
public class Student {
    private int id;
    private String username;
    private String gender;
    private String birthday;
    private String address;

    public Student() {
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", gender='" + gender + '\'' +
                ", birthday='" + birthday + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Student(int id, String username, String gender, String birthday, String address) {
        this.id = id;
        this.username = username;
        this.gender = gender;
        this.birthday = birthday;
        this.address = address;
    }
}


4.编写dao层接口及其实现方法

接口:

package com.wdzl.dao;

import com.wdzl.pojo.Student;

import java.util.List;

/**
 * 学生持久层接口
 */
public interface StudentDao {
    /**
     * 添加
     */
    public void addStudent(Student student);

    /**
     * 修改
     */
    public void updateStudent(Student student);

    /**
     * 删除
     */
    public void deleteStudent(Integer id);

    /**
     * 根据id查询学生详细信息
     */
    public  Student findStudentById(Integer id);

    /**
     * 查询学生总数
     */
    List<Student> findStudentList();

    /**
     * 查询学生总数
     */
    public int total();

    /**
     * 批量增加
     */
    public  void batchAdd(List<Object[]> students);

    /**
     * 批量删除
     */
    public void batchDelete(List<Object[]> students);

    /**
     * 批量修改
     */
    public  void batchUpdate(List<Object[]> students);



}

实现:

package com.wdzl.dao.impl;

import com.wdzl.dao.StudentDao;
import com.wdzl.pojo.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.Arrays;
import java.util.List;

/**
 * 学生持久层实现类
 */
@Repository
public class StudentDaoImpl implements StudentDao{
    //注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public void addStudent(Student student) {
        String sql="insert into student(id,username,gender,birthday,address) values (?,?,?,?,?)";
        int update = jdbcTemplate.update(sql, student.getId(), student.getUsername(), student.getGender(), student.getBirthday(), student.getAddress());
        System.out.println(update);

    }

    @Override
    public void updateStudent(Student student) {
        String sql="update student set address=? where username=?";
        int update = jdbcTemplate.update(sql, student.getAddress(), student.getUsername());
        System.out.println(update);

    }

    @Override
    public void deleteStudent(Integer id) {
       String sql="delete  from student where id=? ";
        int update = jdbcTemplate.update(sql,id);
        System.out.println(update);

    }

    @Override
    public Student findStudentById(Integer id) {
        String sql="select*from student where id=?";
        Student student = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Student.class), id);

        return student;
    }

    @Override
    public List<Student> findStudentList() {
        String sql="select*from student ";
        List<Student> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));

        return query;
    }

    @Override
    public int total() {
        String sql="select count(*) from student ";
        Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);
        return integer;
    }

    @Override
    public void batchAdd(List<Object[]> students) {
        String sql="insert into student(username,gender,birthday,address) values (?,?,?,?)";
        /**
         * 批量增加
         * 参数1:sql语句
         * 参数2:
        */
        int[] ints = jdbcTemplate.batchUpdate(sql, students);
        System.out.println(Arrays.toString(ints));
    }

    @Override
    public void batchDelete(List<Object[]> students) {
        String sql="delete  from student where username=? ";
        int[] ints = jdbcTemplate.batchUpdate(sql, students);
        System.out.println(Arrays.toString(ints));
    }

    @Override
    public void batchUpdate(List<Object[]> students) {
        String sql="update student set address=? where id=?";
        int[] ints = jdbcTemplate.batchUpdate(sql, students);
        System.out.println(Arrays.toString(ints));
    }
}

5.创建service层接口及其实现方法

接口:

package com.wdzl.service;

import com.wdzl.pojo.Student;

import java.util.List;

/**
 * 学生业务成接口
 */
public interface StudentService {
    /**
     * 添加学生
     */
    public void addStudent(Student student);

    /**
     * 修改
     */
    public void updateStudent(Student student);

    /**
     * 删除
     */
    public void deleteStudent(Integer id);

    /**
     * 根据id查询学生详细信息
     */
    public  Student findStudentById(Integer id);

    /**
     * 查询学生总数
     */
    List<Student> findStudentList();

    /**
     * 查询学生总数
     */
    public int total();

    /**
     * 批量增加
     */
    public  void batchAdd(List<Object[]> students);

    /**
     * 批量删除
     */
    public void batchDelete(List<Object[]> username);

    /**
     * 批量修改
     */
    public  void batchUpdate(List<Object[]> students);
}

实现:

package com.wdzl.service.impl;

import com.wdzl.dao.StudentDao;
import com.wdzl.pojo.Student;
import com.wdzl.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;
    @Override
    public void addStudent(Student student) {
        studentDao.addStudent(student);
    }

    @Override
    public void updateStudent(Student student) {
studentDao.updateStudent(student);
    }

    @Override
    public void deleteStudent(Integer id) {
        studentDao.deleteStudent(id);

    }

    @Override
    public Student findStudentById(Integer id) {
        Student studentById = studentDao.findStudentById(id);
       return studentById;
    }

    @Override
    public List<Student> findStudentList() {
        List<Student> studentList = studentDao.findStudentList();
       return studentList;
    }

    @Override
    public int total() {
        int total = studentDao.total();
        return total;
    }

    @Override
    public void batchAdd(List<Object[]> students) {
        studentDao.batchAdd(students);
    }

    @Override
    public void batchDelete(List<Object[]> students) {
        studentDao.batchDelete(students);
    }

    @Override
    public void batchUpdate(List<Object[]> students) {
        studentDao.batchAdd(students);
    }


}

6.编写配置文件

<?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"
       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"
>
<!--    开启组件扫描-->
    <context:component-scan base-package="com.wdzl"></context:component-scan>
<!--数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///mybatis?useUnicode=true&amp;characterEncoding=utf-8"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>

    </bean>

<!--jdbcTempLate    -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>



</beans>

7.测试

import com.wdzl.pojo.Student;
import com.wdzl.service.StudentService;
import com.wdzl.service.impl.StudentServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.List;

public class StudentTest {
@Test
    public void testAddStudent(){
    //1.获取配置文件
    ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
    //2.创建服务层接口对象
    StudentService studentServiceImpl = context.getBean("studentServiceImpl", StudentService.class);
    Student student=new Student(0,"赵童","男","2000-1-1","宝鸡");
    studentServiceImpl.addStudent(student);
}

    @Test
    public void testUpdateStudent(){
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
        //2.创建服务层接口对象
        StudentService studentServiceImpl = context.getBean("studentServiceImpl", StudentService.class);
        Student student=new Student();
        student.setAddress("北京");
        student.setUsername("赵童");

        studentServiceImpl.updateStudent(student);
    }

    @Test
    public void testDeleteStudent(){
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
        //2.创建服务层接口对象
        StudentService studentServiceImpl = context.getBean("studentServiceImpl", StudentService.class);
        studentServiceImpl.deleteStudent(1);
    }

    @Test
    public void testFindStudentById(){
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
        //2.创建服务层接口对象
        StudentService studentServiceImpl = context.getBean("studentServiceImpl",StudentService.class);
        Student studentById = studentServiceImpl.findStudentById(2);
        System.out.println(studentById);
    }

    @Test
    public void testFindStudentList(){
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
        //2.创建服务层接口对象
        StudentService studentServiceImpl = context.getBean("studentServiceImpl",StudentService.class);
        List<Student> studentList = studentServiceImpl.findStudentList();
        for (Student student:studentList){
            System.out.println(student);
        }
    }

    @Test
    public void testFindStudentTotal(){
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
        //2.创建服务层接口对象
        StudentService studentServiceImpl = context.getBean("studentServiceImpl",StudentService.class);
        int total = studentServiceImpl.total();
        System.out.println(total);
    }

    @Test
    public void testAddBatch(){
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
        //2.创建服务层接口对象
        StudentService studentServiceImpl = context.getBean("studentServiceImpl",StudentService.class);
        List<Object[]> args=new ArrayList<>();
        Object[] o1={"王必武","男","2020-2-2","湖南"};
        Object[] o2={"王必武1","男","2020-2-2","湖南"};
        Object[] o3={"王必武2","男","2020-2-2","湖南"};
        Object[] o4={"王必武3","男","2020-2-2","湖南"};
        args.add(o1);
        args.add(o2);
        args.add(o3);
        args.add(o4);

        studentServiceImpl.batchAdd(args);
    }


    @Test
    public void testDelete(){
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
        //2.创建服务层接口对象
        StudentService studentServiceImpl = context.getBean("studentServiceImpl",StudentService.class);
        List<Object[]> args=new ArrayList<>();

        Object[] o1={"王必武"};
       args.add(o1);
        studentServiceImpl.batchDelete(args);




    }

    @Test
    public void testUpdateBatch(){
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans.xml");
        //2.创建服务层接口对象
        StudentService studentServiceImpl = context.getBean("studentServiceImpl",StudentService.class);
        List<Object[]> args=new ArrayList<>();
        Object[] o1={"北京",1};
        Object[] o2={"西安",2};

        args.add(o1);
        args.add(o2);


        studentServiceImpl.batchUpdate(args);
    }


}

8.事务

8.1事务环境搭建

1.新建Module添加相关依赖

2.编写配置文件

  • 配置数据源
  • 配置JDBCTemplate
  • 开启组件扫描

3.编写Dao层接口,Service层接口,及相应的实现类

Dao层

​ 接口

package com.wdzl.dao;

/**
 * 账户持久层接口
 */
public interface AccountDao {
    /**
     * 转入操作
     */
    public  void moneyIn(String name,double money);

    public  void moneyOut(String name,double money);
}

​ 实现

package com.wdzl.dao.Impl;

import com.wdzl.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * 账户持久层实现类
 */
@Repository
public class AccountDaoImpl implements AccountDao {
    //注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public void moneyIn(String name, double money) {
        String sql="update account set money=money+? where name=?";
        int update = jdbcTemplate.update(sql, money, name);
        System.out.println(update);
    }

    @Override
    public void moneyOut(String name, double money) {
        String sql="update account set money=money-? where name=?";
        int update = jdbcTemplate.update(sql, money, name);
        System.out.println(update);

    }
}

Service层

接口

package com.wdzl.service;

public interface AccountService {
    /**
     * 转账操作
     */
    public void transferAccounts(String outName,String inName,double money);
}

实现

package com.wdzl.service.impl;

import com.wdzl.dao.AccountDao;
import com.wdzl.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class AccountServiceImpl implements AccountService {
    //注入AccountDao
    @Autowired
    private AccountDao accountDao;
    @Override
    public void transferAccounts(String outName, String inName, double money) {
        accountDao.moneyIn(inName,money);
//        System.out.println(1/0);
        accountDao.moneyOut(outName,money);

    }
}

4.测试

import com.wdzl.config.TxConfig;
import com.wdzl.service.AccountService;
import com.wdzl.service.impl.AccountServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AccountTest {
    @Test
    public void test(){
        String outName="aa";
        String inName="bb";
        double money=400.00;
        //1.获取配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("Beans2.xml");
        //2.创建服务层接口对象
      AccountService accountService = context.getBean("accountServiceImpl", AccountService.class);
      accountService.transferAccounts(outName,inName,money);

    }

    @Test
    public void test2(){
        String outName="aa";
        String inName="bb";
        double money=400.00;
        //1.获取配置文件
        ApplicationContext context=new AnnotationConfigApplicationContext(TxConfig.class);
        //2.创建服务层接口对象
        AccountService accountService = context.getBean("accountServiceImpl", AccountService.class);
        accountService.transferAccounts(outName,inName,money);

    }
}

8.2事务操作

1.事务因该加入到Service层

  • 因为service层负责组装业务

2.在spring中进行事务管理

  • 编译式事务
  • 声明式事务

3.声明式事务管理

  • 基于注解方式
  • 基于xml方式

4.在spring中进行声明式事务管理使用AOP原理

5.spring针对不同的框架使用了不同的API

  • JDBC,mybatis:DataSourceransTransactionManager
  • Hibernate:HibernateTransactionManager
8.4基于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"
       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.wdzl"></context:component-scan>
<!--数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///test?useUnicode=true&amp;characterEncoding=utf-8"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>

    </bean>

<!--jdbcTempLate    -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

<!-- 创建事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

<!--    配置通知advice-->
    <tx:advice id="txAdvice">
<!-- 配置事务数据-->
        <tx:attributes>
            <tx:method name="transferAccounts" propagation="REQUIRED"/>
        </tx:attributes>


    </tx:advice>

    <!-- 配置切入点和切面-->
    <aop:config>
        <aop:pointcut id="pt" expression="execution(* com.wdzl.service.impl.AccountServiceImpl.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>

    </aop:config>





</beans>
8.3基于注解方式的事务管理

**@Transaction常见配置

  • propagation :事务传播行为
  • isolation: 事务隔离级别
  • timeout:超时时间
  • readOnly:是否只读
  • rollbackFor:回滚
  • noRollbackFor:不回滚

引用配置类(注解)

package com.wdzl.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

/**
 * 配置类
 */
@Configuration//配置类
@ComponentScan(basePackages = "com.wdzl")//开启组件扫描
@EnableTransactionManagement//开启事务
public class TxConfig {
    //配置数据源
    @Bean
    public DruidDataSource getDruidDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///test?useUnicode=true&amp;characterEncoding=utf-8");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

    //配置jdbcTemplate
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    //配置事务管理器
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

}

9.Spring 整合mybatis

9.1注解版声明式事务

1、导⼊依赖坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wdzl</groupId>
    <artifactId>Spring_Mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.16</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

2.创建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>
    <mappers>

<!--引入dao层文件-->
        <mapper class="com.wdzl.dao.AccountDao"></mapper>
    </mappers>
</configuration>




3.提取数据源、SqlSessionFactory

package com.wdzl.jdbc;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;

/**
 * 数据库连接配置类
 */
public class JdbcConfig {
    //用于获取数据源dataSouce的方法
    @Bean//将DataSource注入Spring中
    public DataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }
//用于获取sqlSessionFactory的方法
    @Bean
    public SqlSessionFactoryBean create(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        Resource resource = new ClassPathResource("SqlMapConfig.xml");
        sqlSessionFactory.setConfigLocation(resource);
        return sqlSessionFactory;
    }
}

4.提取事务管理类和配置类

1.事务管理类

package com.wdzl.tx;

import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/**
 * 事务管理类
 */
public class TransactionConfig {
    //获取事务管理对象的方法
    @Bean //注入事务增强类DataSourceTransactionManager
    public PlatformTransactionManager createTransactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}

2.配置类

package com.wdzl.tx;


import com.wdzl.jdbc.JdbcConfig;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * 配置类 相当于bean。xml文件作用
 */
@Configuration//定义配置类
@ComponentScan(basePackages = "com.wdzl")//开启组件扫描
@Import(value = {JdbcConfig.class, TransactionConfig.class})//引入其他配置
@EnableTransactionManagement//开启事务
public class SpringConfig {
}

5.编写pojo–>dao–>service–>controller–>test

pojo

package com.wdzl.pojo;

/**
 * 账户类
 */
public class Account {
    private int id ;
    private String name;
    private double money;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

dao层

接口

package com.wdzl.dao;

import com.wdzl.pojo.Account;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

/**
 * 账户持久层接口
 */
public interface AccountDao {
    /**
     * 根据用户名查询账户信息
     * @param name
     * @return
     */
    @Select("select * from account where name=#{name}")
    Account findAccountByName(String name) ;


    /**
     * 更新账户信息
     * @param account
     */
    @Update("update account set name=#{name},money=#{money} where id=#{id}")
    void updateAccount(Account account);


}

实现类

package com.wdzl.dao.impl;

import com.wdzl.dao.AccountDao;
import com.wdzl.pojo.Account;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * 账户持久层接口实现类
 */
@Repository
public class AccountDaoImpl implements AccountDao {
    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Override
    public Account findAccountByName(String name) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        //获取sqlsession对象
        return accountDao.findAccountByName(name);
    }

    @Override
    public void updateAccount(Account account) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        accountDao.updateAccount(account);

    }
}

service层

接口

package com.wdzl.service;

/**
 * 账户业务层接口
 */
public interface AccountService {
    /**
     * 转账方法
     * @param sourceName 转出账户姓名
     * @param targetName 转入账户姓名
     * @param money 转账金额
     */
    void transfer(String sourceName, String targetName, double money);
}

实现类

package com.wdzl.service.impl;

import com.wdzl.dao.AccountDao;
import com.wdzl.pojo.Account;
import com.wdzl.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 账户业务层实现类
 */
@Service
@Transactional(propagation = Propagation.REQUIRED,readOnly = false)//此⽅法需要加⼊事务,并且为读写事务
public class AccountServiceImpl implements AccountService {
    @Autowired
    //注⼊数据访问层接口
    private AccountDao accountDao;

    public AccountDao getAccountDao() {
        return accountDao;
    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String sourceName, String targetName, double money) {
        //查询转出账户对象
        Account source = accountDao.findAccountByName(sourceName);
        //查询注入账户对象
        Account target = accountDao.findAccountByName(targetName);

        //判断账户是否存在
        if (source !=null && target != null) {
            //设置转出转入金额
            source.setMoney(source.getMoney() - money);
            target.setMoney(target.getMoney() + money);

            //更新账户信息
            accountDao.updateAccount(source);

            accountDao.updateAccount(target);



        }
    }
}


controller层

package com.wdzl.controller;


import com.wdzl.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
/**
 * 账户控制层
 */

@Controller
public class AccountController {
    @Autowired//注入业务接口
    private AccountService accountService;
//为视图提供转账请求接口
    public void transfer(String sourceName, String targetName, double money) {
        try {
            //调用业务层转账方法
            accountService.transfer(sourceName, targetName, money);
            System.out.println("转账成功");
        } catch (Exception e) {
            System.out.println("转账失败");
        }


    }
}

test(测试)

import com.wdzl.controller.AccountController;
import com.wdzl.tx.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AccountTest {
    @Test
    public void test() {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountController accountController = context.getBean("accountController", AccountController.class);
        accountController.transfer("aa", "bb",500);

//        accountController.transfer("王必无","唐康",500.00);
    }
}

结果:转账成功

9.2XML版声明式事务

1.导⼊依赖坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wdzl</groupId>
    <artifactId>Spring_mybatis_xml</artifactId>
    <version>1.0-SNAPSHOT</version>
   <dependencies>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>5.2.7.RELEASE</version>
       </dependency>

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

       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis</artifactId>
           <version>3.5.6</version>
       </dependency>
       <!--mybatis 和 Spring整合包-->
       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis-spring</artifactId>
           <version>2.0.4</version>
       </dependency>
       <!--spring 声明式事务必须所使⽤的依赖坐标-->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-tx</artifactId>
           <version>5.2.7.RELEASE</version>
       </dependency>

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

       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.6</version>
       </dependency>

       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.13</version>
           <scope>test</scope>
       </dependency>

       <dependency>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>1.2.17</version>
       </dependency>
       <dependency>
           <groupId>org.junit.jupiter</groupId>
           <artifactId>junit-jupiter</artifactId>
           <version>RELEASE</version>
           <scope>compile</scope>
       </dependency>
   </dependencies>

</project>

2.创建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>
    <mappers>
<!--引入dao成文件-->
<mapper class="com.wdzl.dao.AccountDao"></mapper>
    </mappers>
</configuration>

3.db.properties ⽂件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

4.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: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-beans.aop">

    <bean id="logger" class="com.wdzl.log.Logger"></bean>

    <bean id="accountService" class="com.wdzl.service.impl.AccountServiceImpl"></bean>


    <aop:config>
        <!--定义切⼊点-->
        <aop:pointcut id="mypointcut" expression="execution(*
com.wdzl.service.impl.*.*(..))"/>
        <!--配置增强处理类-->
        <aop:aspect id="logAdvice" ref="logger">
            <!--将logger类中的⽅法内容通过前置的⽅式植⼊到⽬标⽅法中-->
            <aop:before method="before" pointcut-ref="mypointcut"></aop:before>
            <!--最终增强处理:在没有异常的情况下,此增强内容会被植⼊-->
            <aop:after method="after" pointcut-ref="mypointcut"></aop:after>
            <!--后置增强处理:在有⽆异常的情况下,均进⾏内容增强处理的植⼊-->
            <aop:after-returning method="afterReturning" pointcut-ref="mypointcut" ></aop:after-returning>
        <!--异常增强处理:在异常的情况下,此增强内容会被植⼊ 注:和后置增强处理⼆者不能
       同时出现-->
        <aop:after-throwing method="afterThrowing" pointcut-ref="mypointcut"></aop:after-throwing>
       </aop:aspect>
    </aop:config>

</beans>

5.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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       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
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd

"
>
    <!--引⼊db.properties ⽂件-->
   <context:property-placeholder location="db.properties"></context:property-placeholder>
    <!--注⼊数据访问层实现类-->
    <bean id="accountDao" class="com.wdzl.dao.impl.AccountDaoImpl">
       <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>
    <!--注⼊业务逻辑层-->
<bean id="accountService" class="com.wdzl.service.impl.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"></property>
</bean>

    <!--注⼊控制层-->
    <bean id="accountController" class="com.wdzl.controller.AccountController">
        <property name="accountService" ref="accountService"></property>
    </bean>

    <!--注⼊数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--注⼊sqlsession-->
    <bean id="sqlSessionFactory"
          class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="SqlMapConfig.xml"></property>


    </bean>
    <!--注⼊Spring 声明式事务对象-->
    <bean id="dataSourceTransactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
        <tx:attributes>
            <!--为连接点中的所有⽅法加⼊读写事务-->
            <tx:method name="*" propagation="REQUIRED" read-only="false"/>
            <!--给连接点中所有查询⽅法加⼊只读事务-->
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>

        </tx:attributes>
    </tx:advice>

    <!--aop 配置-->
    <aop:config>
        <!--配置通⽤化切⼊点表达式-->
        <aop:pointcut id="pointcut" expression="execution( *
com.wdzl.service.impl.*.*(..))"/>
        <!--建⽴切⾯-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor>
    </aop:config>


</beans>

6.编写pojo–>log–dao–>service–>controller–>test

1.Logger日志增强类

package com.wdzl.log;

public class Logger {
    public void before(){
        System.out.println("前置增强处理内容被植⼊......");
    }
    public void after(){
        System.out.println("最终增强(有⽆异常均执⾏)处理内容被植⼊......");
    }
    public void afterReturning(){
        System.out.println("后置增强(⽆异常情况)处理内容被植⼊......");
    }
    public void afterThrowing(){
        System.out.println("异常增强处理内容被植⼊......");
    }
}

2.pojo实体类

package com.wdzl.pojo;

/**
 * 账户类
 */
public class Account {
    private int id ;
    private String name;
    private double money;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

3.dao层

接口

package com.wdzl.dao;

import com.wdzl.pojo.Account;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

public interface AccountDao {
    /**
     * 根据用户名查询账户信息
     * @param name
     * @return
     */
    @Select("select * from account where name=#{name}")
    Account findAccountByName(String name) ;


    /**
     * 更新账户信息
     * @param account
     */
    @Update("update account set name=#{name},money=#{money} where id=#{id}")
    void updateAccount(Account account);


}


实现

package com.wdzl.dao.impl;

import com.wdzl.dao.AccountDao;
import com.wdzl.pojo.Account;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * 账户接口实现类
 */
@Repository
public class AccountDaoImpl extends SqlSessionDaoSupport implements AccountDao {

    /**
     * 查询账户信息
     * @param name
     * @return
     */
    @Override
    public Account findAccountByName(String name) {
        //获取session
        SqlSession session = super.getSqlSession();
        AccountDao mapper = session.getMapper(AccountDao.class);
        Account account = mapper.findAccountByName(name);
        //释放资源
        return account;
    }
    /**
     * 更新账户信息
     * @param account
     */
    @Override
    public void updateAccount(Account account) {
        SqlSession session = super.getSqlSession();
        AccountDao mapper = session.getMapper(AccountDao.class);
        mapper.updateAccount(account);
    }
}


4。service层

接口

package com.wdzl.service;

public interface AccountService {
    /**
     *转账业务
     */
    void transfer(String sourceName, String targetName, double money);

    void testLog();
}

实现

package com.wdzl.service.impl;

import com.wdzl.dao.AccountDao;
import com.wdzl.log.Logger;
import com.wdzl.pojo.Account;
import com.wdzl.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class AccountServiceImpl implements AccountService {
    public AccountDao getAccountDao() {
        return accountDao;
    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    private AccountDao accountDao;

    @Override
    public void transfer(String sourceName, String targetName, double money) {
        //查询转出账户对象
        Account source = accountDao.findAccountByName(sourceName);
        //查询注入账户对象
        Account target = accountDao.findAccountByName(targetName);

        //判断账户是否存在
        if (source !=null && target != null) {
            //设置转出转入金额
            source.setMoney(source.getMoney() - money);
            target.setMoney(target.getMoney() + money);

            //更新账户信息
            accountDao.updateAccount(source);

            accountDao.updateAccount(target);



        }
    }


    private Logger logger;

    public Logger getLogger() {
        return logger;
    }

    public void setLogger(Logger logger) {
        this.logger = logger;
    }

    @Override
    public void testLog() {

        System.out.println("测试日志增强有没有加入");


    }
}


5.controller层

package com.wdzl.controller;


import com.wdzl.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class AccountController {
    public AccountService getAccountService() {
        return accountService;
    }

    public void setAccountService(AccountService accountService) {
        this.accountService = accountService;
    }

    private AccountService accountService;

    public void transfer(String sourceName, String targetName, double money) {
        try {
            accountService.transfer(sourceName, targetName, money);
            System.out.println("转账成功");
        } catch (Exception e) {
            System.out.println("转账失败");
        }


    }
}

6.test测试

LoggerTest测试类

import com.wdzl.service.AccountService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LoggerTest {
    private ApplicationContext context;
    @Test
    public void testLog(){
        AccountService accountService = context.getBean("accountService", AccountService.class);
        accountService.testLog();
    }
    @Before
    public void springinit(){
        context = new ClassPathXmlApplicationContext("bean2.xml");
    }

}

结果

前置增强处理内容被植⼊…
测试日志增强有没有加入
最终增强(有⽆异常均执⾏)处理内容被植⼊…
后置增强(⽆异常情况)处理内容被植⼊…

AccountControllerTest测试类

import com.wdzl.controller.AccountController;
import com.wdzl.service.AccountService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AccountControllerTest {
    private ApplicationContext context;
    @Before
    public void springinit(){
        context = new ClassPathXmlApplicationContext("bean.xml");
    }

    @Test

    public void testTransfer(){
        AccountController accountController =
                context.getBean("accountController", AccountController.class);
        accountController.transfer("aa","bb",5000);
    }

    @Test
    public void test(){
        AccountService accountService = context.getBean("accountService", AccountService.class);
        accountService.testLog();
    }
}

结果:

1.转账成功

2.测试日志增强有没有加入

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值