• Spring框架开发的三种模式


    第一节 IoC的综合案例 - 纯xml开发

    1.1综合案例描述

    案例的需求

    实现账户表的增删改查操作

    案例的要求

    选用基于XML的Spring和Mybatis整合配置实现。

    • 数据库表结构介绍
    CREATE TABLE `account` (
    `id`  int(11) NOT NULL ,
    `name`  varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
    `money`  double NULL DEFAULT NULL ,
    PRIMARY KEY (`id`)
    )
    ENGINE=InnoDB
    DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
    ROW_FORMAT=COMPACT
    

    1.2 案例的实现

    1.2.1 创建工程导入坐标

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    

    1.2.2 编写基础代码

    /**
     * 账户的实体类
     */
    public class Account {
    
        private Integer id;
        private String name;
        private Double money;
    
    	//省略set,get,toString等方法
    }
    
    /**
     * 账户的业务层接口
     */
    public interface AccountService {
        /**
         * 保存
         */
        void save(Account account);
    
        /**
         * 根据id删除
         */
        void delete(Integer id);
    
        /**
         * 更新账户
         */
        void update(Account account);
    
        /**
         * 根据id查询
         */
        Account findById(Integer id);
    
        /**
         * 根据名称查询账户
         */
        Account findByName(String name);
    
        /**
         * 查询所有
         */
        List<Account> findAll();
    }
    
    
    /**
     * 账户业务接口实现类
     */
    public class AccountServiceImpl implements AccountService {
    
         // 依赖注入  通过依赖注入可以实现service调用dao的增删改查方法 通过方法进行增删改查的调用
        // 调用dao的时候要有接口所对应的SQL文件
        private AccountDao accountDao;
    
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
    
        @Override
        public void save(Account account) {
            accountDao.save(account);
        }
    
        @Override
        public void delete(Integer id) {
            accountDao.delete(id);
        }
    
        @Override
        public void update(Account account) {
            accountDao.update(account);
        }
    
        @Override
        public Account findById(Integer id) {
            return accountDao.findById(id);
        }
    
        @Override
        public Account findByName(String name) {
            return accountDao.findByName(name);
        }
    
        @Override
        public List<Account> findAll() {
            return accountDao.findAll();
        }
    }
    
    
    /**
     * 账户持久层接口
     */
    public interface AccountDao {
        /**
         * 保存
         */
        void save(Account account);
    
        /**
         * 根据id删除
         */
        void delete(Integer id);
    
        /**
         * 更新账户
         */
        void update(Account account);
    
        /**
         * 根据id查询
         */
        Account findById(Integer id);
    
        /**
         * 根据名称查询账户
         */
        Account findByName(String name);
    
        /**
         * 查询所有
         */
        List<Account> findAll();
    }
    

    1.2.3 编写mybatis的映射配置

    <?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">
    <mapper namespace="com.itheima.dao.AccountDao">
    
        <!--保存-->
        <insert id="save" parameterType="account">
            insert into account values(#{id},#{name},#{money})
        </insert>
    
        <!--根据id删除-->
        <delete id="delete" parameterType="int" >
            delete from account where id=#{id}
        </delete>
    
        <!--更新账户-->
        <update id="update" parameterType="account">
            update account set name=#{name},money=#{money} where id=#{id}
        </update>
    
        <!--根据id查询-->
        <select id="findById" parameterType="int" resultType="account">
            select * from account where id=#{id}
        </select>
    
        <!--根据名称查询账户-->
        <select id="findByName" parameterType="string" resultType="account">
            select * from account where name=#{name}
        </select>
    
        <!--查询所有-->
        <select id="findAll" resultType="account">
            select * from account
        </select>
    </mapper>
    

    1.2.4 连接数据库

    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/database?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    jdbc.username=root
    jdbc.password=root
    # 连接数据库
    

    1.2.5 编写spring和mybatis整合配置

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring配置文件并导入约束 -->
    <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 https://www.springframework.org/schema/context/spring-context.xsd">
        <!-- SpringContext spring核心配置文件 -->
        <!-- dao层内容 -->
        <!-- 1.连接数据库的配置文件 -->
        <context:property-placeholder location="classpath:jdbc.properties"/>
        <!-- 2.配置Druid数据源 -->
        <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${jdbc.driverClassName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
        <!-- 3.配置SqlSessionFactory的对象 是为了让spring完成mybatis的对象创建的时候,可以知道通过SqlSessionFactoryBean就能帮助找到mybatis所用到的sqlsession -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 数据源 -->
            <property name="dataSource" ref="druidDataSource"/>
            <!-- pojo的别名映射-->
            <property name="typeAliasesPackage" value="com.zhuxu.pojo"/>
        </bean>
        <!-- 4.配置dao层代码动态代理对象生成的扫描器 -->
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!-- 指定扫描的dao层的路径 -->
            <property name="basePackage" value="com.zhuxu.dao"/>
        </bean>
        <!-- 5.service层内容 spring的配置 -->
        <bean id="accountService" class="com.zhuxu.service.impl.AccountServiceImpl">
            <!-- 依赖注入 -->
            <property name="accountDao" ref="accountDao"/>
        </bean>
    </beans>
    
    

    1.2.6 测试

    /*
    测试类
     */
    public class CRUDTest {
        @Test
        public void findByName(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
            AccountService accountService = applicationContext.getBean(AccountService.class);
            Account account = accountService.findByName("迪丽热巴");
            System.out.println("account = " + account);
        }
    
        @Test
        public void findAll(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
            AccountService accountService = applicationContext.getBean(AccountService.class);
            List<Account> accountList = accountService.findAll();
            for (Account account : accountList) {
                System.out.println("account = " + account);
            }
        }
    }
    

    第二节 注解开发

    2.1 bean标签和注解的对应

    • bean标签对应注解@Component对应的是把xml配置文件中impl文件替换掉 替换如下的代码

    • 如:

      @Component("accountDao")
      public class AccountDaoImpl implements AccountDao {
          @Override
          public void saveAccount() {
              System.out.println("模拟保存账户");
          }
      }
      

      就不用在xml中写以下代码

      <!--配置accountService对象-->
      <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
      

      但是beans.xml配置没有指定接口实现类对象所以就需要开启springioc的注解扫描,扫描包中类的注解

      <context:component-scan base-package="com.itheima"></context:component-scan>
      
      • 注解属性value:bean标签的id属性
      • 不指定value属性,默认就是类名,首字母小写
      • 该注解衍生出了三个注解,@Controller(在servlet层),@Service(service层),@Repository(dao层 ),用法和@Componet一致,为了更加清晰的提现层的概念。
    • bean标签属性scope对应注解@Scope

      • 注解属性value:singleton,prototype
    • bean标签属性init-method对应注解@PostConstruct 构造方法执行完毕后执行

    • bean标签属性destroy-method对应注解@PreDestroy 对象销毁前执行的方法

    • service层

      public interface AccountService {
      
          //模拟保存账户
          void save();
      }
      
      //@Component("accountService")
      @Service("accountService")
      @Scope("prototype")
      public class AccountServiceImpl implements AccountService {
      
          private AccountDao accountDao;
      
          public void setAccountDao(AccountDao accountDao) {
              this.accountDao = accountDao;
          }
      
          @Override
          public void saveAccount() {
              accountDao.saveAccount();
          }
      }
      
    • dao层

      public interface AccountDao {
      
          //模拟保存账户
          void save();
      }
      
      //@Component("accountDao")
      @Repository("accountDao")
      public class AccountDaoImpl implements AccountDao {
          @Override
          public void saveAccount() {
              System.out.println("保存了账户");
          }
      
          private void init() {
              System.out.println("AccountDao对象初始化");
          }
      
          private void destroy() {
              System.out.println("AccountDao对象 销毁了");
          }
      }
      
    • 添加applicationContext配置文件命名空间

      <?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"
      >
          
          <!-- 开启spring的注解扫描,扫描包中类的注解-->
          <context:component-scan base-package="com.itheima"></context:component-scan>
      </beans>
      
    • 测试注解

      @Test
      public void testIOC(){
          ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
          AccountService accountService = context.getBean(AccountService.class);
          AccountDao accountDao = context.getBean(AccountDao.class);
      
          System.out.println(accountService);
          System.out.println(accountDao);
      
          context.close();
      }
      

    2.2 依赖注入注解

    之前是私有化一对象,通过get或者set的方法进行依赖注入

       private AccountDao accountDao;
    
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
    
    • @Autowired注解(Spring框架提供)通过类型自动注入

      @Autowired
      private AccountDao accountDao;
      
    • 当接口的实现类不止一个时,无法通过类型自动注入了

      按照类型注入,如果无法确定唯一类型(接口有多个实现类),需要配合注解@Qualifier的使用

    • @Qualifier("id") 注解(Spring框架提供)

      • 按照id注入
    • @Resource注解(JDK提供)

      • 注解属性name:配置类的id
    @Resource(name="accountDao")
    private AccountDao accountDao;
    

    代码演示

    • 业务层
    @Service("accountService")
    @Scope("singleton")
    public class AccountServiceImpl implements AccountService {
    
         @Autowired
        //@Qualifier("accountDao2")
        //@Resource(name = "accountDao2")
        private AccountDao accountDao;
    
        @Override
        public void saveAccount(Account account) {
            accountDao.saveAccount(account);
        }
    }
    
    • dao层
    package com.itheima.dao.impl;
    
    /**
     * 账户dao实现类
     */
    @Component("accountDao")
    //@Repository("accountDao")
    @Scope("singleton")
    public class AccountDaoImpl implements AccountDao {
    
        @Override
        public void saveAccount(Account account) {
            System.out.println("模拟转账");
        }
    
        @PostConstruct()
        public void init(){
            System.out.println("AccountDaoImpl 初始化...");
        }
    
        @PreDestroy
        public void destroy(){
            System.out.println("AccountDaoImpl 销毁...");
        }
    }
    
    

    2.3 Spring对Junit的支持

    • junit运行的时候底层使用了Runner对象,有一个默认使用的Runner对象。
    • Spring对junit的支持,其实是自己实现了一个Runner对象(按照junit runner的要求实现)
    • Spring对junit的支持的体现
      • 好处一:配置完之后,不需要我们手动的启动Spring
      • 好处二:可以在junit测试类中使用@AutoWired等方式注入对象,直接对其进行调用测试
    • 使用步骤
      • 引入spring-test.jar包
      • 配置测试类
      //Spring框架中的Runner对象, 替换Junit中的Runner对象 (更换启动器  或者叫更换执行对象)
      @RunWith(SpringJUnit4ClassRunner.class)
    
      //框架启动入口, xml配置文件启动(2选1)加载xml启动执行配置文件  可以加载多个配置文件
      @ContextConfiguration(locations = "classpath:beans.xml")
      //框架启动入口, 注解方式配置文件启动(2选1)  纯注解开发推荐使用
      //@ContextConfiguration(classes = SpringConfig.class)
    
    • 代码实现

      • pom.xml
      <dependencies>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context</artifactId>
              <version>5.1.9.RELEASE</version>
          </dependency>
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.12</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-test</artifactId>
              <version>5.1.9.RELEASE</version>
          </dependency>
      </dependencies>
      
      • 测试类
      package com.itheima;
      
      //Spring框架中的Runner对象, 替换Junit中的Runner对象
      @RunWith(SpringJUnit4ClassRunner.class)
      //框架启动入口, 注解方式配置文件启动
      //@ContextConfiguration(classes = SpringConfig.class);
      //框架启动入口, xml配置文件启动
      @ContextConfiguration(locations = "classpath:ApplicationContext.xml")
      public class AccountTest {
      
          //注入业务层接口
          @Autowired
          private AccountService service;
      
          @Test
          public void testIOC(){
      
              System.out.println("service = " + service);
              Account account = new Account();
              account.setName("小米");
              account.setMoney(888.0F);
              service.saveAccount(account);
          }
      }
      

    第三节 IoC的综合案例(CRUD) - 半注解半xml开发

    企业主流的开发方式

    注意:往往第三方jar中的对象我们使用xml配置(比如druid数据库连接池、Mybatis的SQLSessionFactory),类似于service层和dao层的实现类,这属于我们自己写的代码,往往会使用注解,这就是半xml半注解的模式。

    • applicationContext.xml配置

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
      
          <!--配置dao-->
          <!--配置properties文件的位置-->
          <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
          <!--配置数据源-->
          <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
              <property name="driverClassName" value="${jdbc.driverClassName}"></property>
              <property name="url" value="${jdbc.url}"></property>
              <property name="username" value="${jdbc.username}"></property>
              <property name="password" value="${jdbc.password}"></property>
          </bean>
          <!--配置mybatis的SqlSessionFactory工厂-->
          <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
              <property name="dataSource" ref="druidDataSource"></property>
              <property name="typeAliasesPackage" value="com.itheima.pojo"></property>
          </bean>
          <!--配置创建dao代理实现类的扫描器-->
          <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
              <property name="basePackage" value="com.itheima.dao"></property>
          </bean>
      
          <!--配置service-->
          <!--让Spring开启注解扫描-->
          <context:component-scan base-package="com.itheima"></context:component-scan>
      </beans>
      
    • service层

      package com.itheima.service.impl;
      
      /**
       * 账户业务接口实现类
       */
      @Service("accountService")
      public class AccountServiceImpl implements AccountService {
      
          //依赖注入
          @Autowired
          private AccountDao accountDao;
      
          //增删改查方法 无修改, 笔记中代码省略
          
      }
      
    • 测试类

    /*
    测试类
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:ApplicationContext.xml"})
    public class AccountServiceTest {
    
        @Autowired
        private AccountService accountService;
    
        //测试类方法省略
        @Test
        public void findAll() {
            List<Account> accountList = accountService.findAll();
            for (Account account : accountList) {
                System.out.println("account = " + account);
            }
        }
    }
    

    第四节 IoC的综合案例(CRUD) - 纯注解开发

    • @Configuration标识当前类是Spring的一个配置类

    • @ComponentScan替代xml中的<context:component-scan/>

    • @Import引入其他配置类,被引入的配置类可以不加@Configuration注解

    • @PropertySource:引入外部properties文件,注意加classpath:

    • @Value对成员变量赋值

    • @Bean将一个方法的返回值对象加入到Spring的容器当中管理

    • @Qualifier可以使用在方法参数上,表明对应的形参引入/注入的对象类型

    4.1 SpringConfig框架启动配置类

    只要在一个类上加@Configuration,那么这个类就是spring的配置类

    /**
     * Spring框架的核心配置文件(注解配置)
     * @author Lucky
     * @date 2020/8/29
     */
    // 标识当前类是spring的一个配置类
    @Configuration
    // 开启SpringIOC容器的注解扫描
    /**
     * xml代码
     *   <!-- 扫描包,开启注解 -->
     *     <context:component-scan base-package="com.zhuxu" />
     * */
    
    @ComponentScan({"com.zhuxu"})
    // 加载properties配置文件
    // @PropertySource({"classpath:jdbc.properties"})
    public class SpringConfig {
        // 配置数据源
        /**
         * xml源码
         * <!-- 配置Druid数据源 -->
         *     <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
         *         <property name="driverClassName" value="${jdbc.driverClassName}"/>
         *         <property name="url" value="${jdbc.url}"/>
         *         <property name="username" value="${jdbc.username}"/>
         *         <property name="password" value="${jdbc.password}"/>
         *     </bean>
         */
        @Bean("druidDataSource")
        public DataSource createDataSource(){
            DruidDataSource druidDataSource = new DruidDataSource();
            // 配置相关驱动信息(驱动、url、用户名、密码)
            druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
            druidDataSource.setUrl("jdbc:mysql://localhost:3306/ssm_lx");
            druidDataSource.setUsername("root");
            druidDataSource.setPassword("root");
    
            return  druidDataSource;
    
        }
    
        // 配置SqlSessionFactory对象
        // 参数DataSource dataSource,会自动从Spring IOC容器中找配置的Bean对象
        /**
         * 配置SqlSessionFactory对象xml源码
         * <!-- 配置SqlSessionFactory的对象 是为了让spring完成mybatis的对象创建的时候,可以知道通过SqlSessionFactoryBean就能帮助找到mybatis所用到的sqlsession
         * -->
         *     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
         *         <!-- 数据源 -->
         *         <property name="dataSource" ref="druidDataSource"/>
         *         <!-- pojo的别名映射-->
         *         <property name="typeAliasesPackage" value="com.zhuxu.pojo"/>
         *     </bean>
         * */
        @Bean
        public SqlSessionFactoryBean createSqlSessionFactoryBean(@Qualifier("druidDataSource") DataSource dataSource){
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            // 配置相关信息(数据源,pojo别名)
            sqlSessionFactoryBean.setDataSource(dataSource);
            sqlSessionFactoryBean.setTypeAliasesPackage("com.zhuxu.pojo");
    
            return sqlSessionFactoryBean;
        }
    
        /**
         * xml代码
         *     <!-- 配置dao层代码动态代理对象生成的扫描器 -->
         *     <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
         *         <!-- 指定扫描的dao层的路径 -->
         *         <property name="basePackage" value="com.zhuxu.dao"/>
         *     </bean>
         * */
        // dao 扫描器
        @Bean
        public MapperScannerConfigurer createMapperScannerConfigurer(){
            MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer();
            // 配置相关信息(指定扫描的dao层的路径)
            scannerConfigurer.setBasePackage("com.zhuxu.dao");
            return scannerConfigurer;
        }
    
    
    
    }
    
    • 测试
    /*
    测试类
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    //框架启动入口, 注解方式配置文件启动(2选1)
    @ContextConfiguration(classes = SpringConfig.class)
    public class CRUDTest {
    
        @Autowired
        private AccountService accountService;
    
        @Test
        public void findByName(){
            Account account = accountService.findByName("迪丽热巴");
            System.out.println("account = " + account);
        }
    
        @Test
        public void findAll(){
            List<Account> accountList = accountService.findAll();
            for (Account account : accountList) {
                System.out.println("account = " + account);
            }
        }
    }
    

    4.2 注解开发的SpringConfig配置优化

    • SpringConfig框架启动配置类

      /*
      作为Spring框架的主配置文件
       */
      @Configuration
      //开启Spring容器的注解扫描
      @ComponentScan({"com.itheima"})
      //导入子配置文件
      @Import({JDBCConfig.class, MybatisConfig.class})
      public class SpringConfig {
      
      }
      
    • JDBCConfig配置类

      //用于指定与数据库相关配置的配置文件
      @Configuration
      @PropertySource({"classpath:jdbc.properties"})
      public class JDBCConfig {
      
          @Value("${jdbc.driverClassName}")
          private String driverClassName;
          @Value("${jdbc.url}")
          private String url;
          @Value("${jdbc.username}")
          private String username;
          @Value("${jdbc.password}")
          private String password;
      
          //配置数据源
          @Bean("ataSource")
          public DataSource createDataSource(){
              //创建Druid数据源
              DruidDataSource druidDataSource = new DruidDataSource();
              //配置相关信息(Driver, url, username, password)
              druidDataSource.setDriverClassName(driverClassName);
              druidDataSource.setUrl(url);
              druidDataSource.setUsername(username);
              druidDataSource.setPassword(password);
      
              return druidDataSource;
          }
      }
      
    • Mybatis配置类

      //用于配置与Mybatis相关的配置
      @Configuration
      public class MybatisConfig {
          //配置SqlSessionFactoryBean对象
          @Bean("sqlSessionFactory")
          public SqlSessionFactoryBean createSqlSessionFactoryBean(DataSource ds){
              //创建SqlSessionFactoryBean 对象
              SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
              //配置相关信息(数据源, pojo别名映射)
              sqlSessionFactory.setDataSource(ds);
              sqlSessionFactory.setTypeAliasesPackage("com.itheima.pojo");
      
              return sqlSessionFactory;
          }
      
          //配置dao的包扫描
          @Bean("scannerConfigurer")
          public MapperScannerConfigurer createMapperScannerConfigurer(){
              //创建MapperScannerConfigurer 对象
              MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer();
              //配置相关信息(扫描的dao包, 找到了dao层的接口文件, 找到了SQL映射文件, 生成接口实现类对象并存到Spring容器中)
              scannerConfigurer.setBasePackage("com.itheima.dao");
      
              return scannerConfigurer;
          }
      }
      
    • 测试类

      /*
      测试类
       */
      @RunWith(SpringJUnit4ClassRunner.class)
      //加载的xml配置文件
      //@ContextConfiguration(locations = {"classpath:ApplicationContext.xml"})
      
      //加载的注解形式的Spring主配置文件
      @ContextConfiguration(classes = {SpringConfig.class})
      public class AccountServiceTest {
      
          @Autowired
          private AccountService accountService;
      	
          //其他方法省略
      
          @Test
          public void findAll() {
              List<Account> accountList = accountService.findAll();
              for (Account account : accountList) {
                  System.out.println("account = " + account);
              }
          }
      }
      

    第五节 案例:模拟转账

    案例:模拟转账(并且模拟转账异常)

    • 汇款人账户减少一定的金额
    • 收款人账户增加一定的金额
    • 计算之后,更新数据库
    • 问题:模拟转账异常(人为制造异常,在两次update之间造了异常)

    5.1 转账编码

    1、引入依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
    </dependencies>
    
    2、业务层
    /**
     * 账户的业务层接口
     */
    public interface AccountService {
        /**
         * 转账
         */
        void transfer(String source, String target, double money);
        
        //其他方法省略
    }
    
    /**
     * 账户业务接口实现类
     */
    @Service("accountService")
    public class AccountServiceImpl implements AccountService {
    
        //依赖注入
        @Autowired
        private AccountDao accountDao;
    
        /*
        转账业务逻辑
        1.先查询账户信息
        2.修改账户信息
        3.持久化账户信息
         */
        @Override
        public void transfer(String source, String target, double money) {
            try {
                //开启事务
    
                // 转账业务逻辑
                //1 先查询账户信息
                Account sourceAccount = accountDao.findByName(source);
                Account targetAccount = accountDao.findByName(target);
                //2 修改账户信息
                sourceAccount.setMoney(sourceAccount.getMoney() - money);
                targetAccount.setMoney(targetAccount.getMoney() + money);
                //3 持久化账户信息
                accountDao.update(sourceAccount);
                //int i = 1/0;
                accountDao.update(targetAccount);
    
                //提交事务
            } catch (Exception e){
                e.printStackTrace();
                //回滚事务
    
            } finally {
                //关闭资源
            }
        }
        
        //其他方法省略
    }
    
    3、测试
    /*
    测试类
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:ApplicationContext.xml")
    public class CRUDTest {
    
        @Autowired
        private AccountService accountService;
    
        @Test
        public void tranfer(){
            accountService.transfer("迪丽热巴","古力娜扎",1);
        }
    }
    
    4、发现问题
    转账过程出现事务问题
    
  • 相关阅读:
    linux常用命令
    虚函数、纯虚函数、虚函数表、虚析构函数(一)
    有没有easyx库文件
    请教那位老师帮忙修重新改按键定义
    C语言txt文件元素追加
    do-while是如何控制指针+1的呢
    printf后的句子怎么显示啊
    如何用C语言生成高斯粗糙面
    读取文件时程序报错调试了好久不知道如何解决
    新人求教:字符串在文件输入中的整体输入
  • 原文地址:https://www.cnblogs.com/anke-z/p/13583009.html
Copyright © 2020-2023  润新知