其他分享
首页 > 其他分享> > Spring框架01-IoC基础及XML的配置

Spring框架01-IoC基础及XML的配置

作者:互联网

1. Spring概述

1.1 关于框架

学好框架的必要性

spring(包括springmvc)和mybatis是企业开发中最基础的两个框架。

接下来,从企业角度分析,在实际开发中通常都会采用成熟的框架作为项目某个技术的解决方案,而掌握这些基础框架已经是企业对开发人员的最基本技能要求。

从自身角度分析,我们通过前面对mybatis框架的学习和使用,在实现持久层操作时代码变得精简的同时,开发时间得到了大大的缩短。

1.2 Spring概述

官网地址:https://spring.io/

1.2.1 Spring简介

Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IOC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 SpringMVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架 .

1.2.2 Spring的优势

2. 控制反转IoC - Inverse Of Control

2.1 程序的耦合

2.1.1 什么是耦合

耦合性(Coupling),也叫耦合度,它是对模块间关联程度的度量。

在软件工程中,耦合指的就是对象之间的依赖关系。对象之间的耦合越高,则表明模块的独立性和可复用性越差,且维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则是:高内聚低耦合。

2.1.2 内聚和耦合

2.1.3 耦合的示例

最明显的一个因程序耦合而不得不改变的技术点就是JDBC操作的注册驱动:

/**
 * 程序的耦合演示
 */
public class JdbcDemo {

    /**
     * JDBC操作
     */
    public static void main(String[] args) throws Exception{
        //1.注册驱动
        //此处我们的代码中依赖了mysql的具体驱动实现,而实际开发中,当我们要更改数据库实现,就需要修改此处的源代码。
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //2.获取连接
        //3.获取预处理对象
        //4.执行sql语句
        //5.处理结果集
        //6.释放资源
    }
}

2.2 工厂模式解耦

2.2.1 解耦及其必要性

解耦,顾名思义,即解除耦合,消除依赖关系。但是在程序开发中,如果两个模块协同工作,则必然存在耦合。如果两个模块间没有任何依赖关系,则表示他们是独立的,不会有任何交叉或者协同工作的可能性。所以,我们这里说的解耦并非消除代码间的耦合,而是降低它们的依赖关系,让依赖关系处在一个合理的范围。

低耦合的程序设计是我们开发中的一个最基本要求,它会使我们开发的功能独立性提高,大大增加了模块的复用性。同时,在后期对项目维护时,降低了维护成本、项目做后续升级时,减少了重构的风险。它是一个合格的程序员所必须具备的设计理念。

2.2.2 解耦的思路分析

当时使用jdbc 时,是通过反射来注册驱动的,已经不会采用DriverManager.registerDriver()方法来注册驱动了,因为当时我们介绍一种更好的方式Class.forName(),通过反射的方式也能实现注册驱动的功能。那这两种方式,在本质上有什么区别呢?

DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");//此处只是一个字符串

2.2.3 设计模式-工厂模式

工厂模式是我们最常用的实例化对象模式了,它是用工厂中的方法代替new创建对象的一种设计模式。

我们以Mybatis的SqlSession接口为例,它有一个实现类DefaultSqlSession,如果我们要创建该接口的实例对象:

SqlSession sqlSession = new DefaultSqlSession();

可是,实际情况是,通常我们都要在创建SqlSession实例时做点初始化的工作,比如解析XML,封装连接数据库的信息等等。

在创建对象时,如果有一些不得不做的初始化操作时,我们首先到的是,可以使用构造函数,这样生成实例就写成:

SqlSession sqlSession = new DefaultSqlSession(传入配置文件的路径);

但是,如果创建sqlSession实例时所做的初始化工作不是像赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,那你的代码很难看了(这时候就需要代码Refactor重构)。

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build("SqlMapConfig.xml");
SqlSession sqlSession = factory.openSession();

所以,Mybatis框架在使用时为我们提供了SqlSessionFactory工厂类,通过openSession()方法获取到SqlSession对象。openSession()同时方法有很多重载,用于实现不同的需求。它支持传入Connection参数来保证连接的一致性;支持传入true|false来保证事务的提交时机等等。

2.2.4 运用工厂模式解耦

下面模拟实现Spring中的解耦方法,其实就是之前博客中写的用dom4j解析xml文档,具体步骤如下:

步骤1: 创建业务层接口和实现类
/**
* 账户的业务层接口
*/
public interface AccountService {
    /**
    * 保存账户(此处只是模拟,并不是真的要保存)
    */
    void saveAccount();
}
/**
* 账户的业务层实现类
*/
public class AccountServiceImpl implements AccountService {
    	
    /* 
     在我们使用三层架构作为开发基础时,层和层之间的调用,如果使用具体实现类就会出现内容依赖。
     在需要更换实现时,就需要修改源码,造成当前业务层功能的独立性很差。同时给我们维护带来极大不便。
     */
    //此处的依赖关系有待解决
    //private AccountDao accountDao = new AccountDaoImpl();
    
    //使用工厂模式获取dao对象
    private AccountDao accountDao = (AccountDao)BeanFactory.getBean("AccountDao");
    
    @Override
    public void saveAccount() {
    	accountDao.saveAccount();
    }
}
步骤2: 创建持久层接口和实现类
/**
* 账户的持久层接口
*/
public interface AccountDao {
    /**
    * 保存账户
    */
    void saveAccount();
}
/**
* 账户的持久层实现类
*/
public class AccountDaoImpl implements AccountDao {
    @Override
    public void saveAccount() {
    	System.out.println("保存了账户");
    }
}
步骤3: 配置文件 beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <!-- 配置 service -->
    <bean id="AccountService" class="com.szz.service.impl.AccountServiceImpl"></bean>
    <!-- 配置 dao -->
    <bean id="AccountDao" class="com.szz.dao.impl.AccountDaoImpl"></bean>
</beans>
步骤4: 工具类

/**
 * Bean工厂:创建对象
 * 步骤:
 *  1. 解析xml,获取所有对象的全限定类型(全名称)
 *  2. 反射创建对象,存储到容器中
 *      容器:有查找的需求,使用map集合
 *  3. 用户需要对象时,从容器中根据id直接获取
 */
public class BeanFactory {
    // String: id , Object : 反射创建好的对象
    private static Map<String,Object> map = new HashMap<>();
    //静态代码块:类加载时执行,只会执行一次
    static {
        //解析xml,获取所有对象的全限定类型(全名称)
        SAXReader reader = new SAXReader();
        try {
            //获取文档对象
            Document doc = reader.read(BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml"));
            //获取根节点
            Element rootElement = doc.getRootElement();
            //获取根节点下的所有的子节点
            List<Element> elements = rootElement.elements();
            //遍历
            for (Element element : elements) {
                String idValue = element.attributeValue("id");
                String classValue = element.attributeValue("class");
                //反射创建对象,存储到容器中
                Class clazz = Class.forName(classValue);
                Object obj = clazz.newInstance();
                //存储到容器中
                map.put(idValue, obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Object  getBean(String id){
        return map.get(id);
    }
}

步骤5: 测试
public class AccountTest {
    public static void main(String[] args) {
        //创建业务层对象, 调用save方法
        AccountService accountService = new AccountServiceImpl();

      	//AccountService accountService = (AccountService) BeanFactory.getBean("AccountService");
        //accountService.saveAccount();

        AccountDao accountDao = (AccountDao) BeanFactory.getBean("AccountDao");
        accountDao.saveAccount();
    }
}

2.3 关于IoC

2.3.1 什么是IoC

它的全称是Inversion Of Control,意为控制反转。它不是一个技术,而是一种思想。其作用是用于削减代码间的耦合。它的实现思想就是利用了工厂设计模式,把创建对象代码从具体类中剥离出去,交由工厂来完成,从而降低代码间的依赖关系。

2.3.2 IoC的实现思路分析

传统方式

在这里插入图片描述

使用IoC后

在这里插入图片描述

IoC的作用

明确:它是用于降低我们代码间的依赖关系,削减程序中的耦合。

3. Spring的IoC入门

3.1 Spring基于XML的的配置(入门案例)

步骤1: 导入jar包依赖 pom.xml
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
</dependencies>
步骤2: 创建Spring的配置文件 beans.xml (文件名可任意起名)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
步骤3: 让Spring管理资源, 在配置文件中配置service和dao
<!-- bean 标签:用于配置让 spring 创建对象,并且存入 ioc 容器之中
    id 属性:对象的唯一标识。
    class 属性:指定要创建对象的全限定类名
-->
<!-- 配置 service -->
<bean id="accountService" class="com.szz.service.impl.AccountServiceImpl"></bean>
<!-- 配置 dao -->
<bean id="accountDao" class="com.szz.dao.impl.AccountDaoImpl"></bean>
步骤4:测试配置是否成功
/**
 * 测试spring基于xml的Ioc入门案例
 */
public class SpringIocTest {

    /**
     * 步骤分析:
     *    第一步:创建容器
     *    第二步:根据bean的唯一标识获取对象
     *    第三步:执行方法
     */
    public static void main(String[] args) {
        //1.使用 ApplicationContext 接口,就是在获取 spring 容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        //2.根据 bean 的 id 获取对象
        AccountService accountService = (AccountService) ac.getBean("accountService");
        System.out.println(accountService);

        AccountDao accountDao = (AccountDao) ac.getBean("accountDao");
        System.out.println(accountDao);
    }
}

4. 基于XML的IOC深入

4.1 XML的IOC细节

4.1.1 Spring中工厂类结构图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iAJ57gwT-1610873456648)(assets/1569641865437.png)]

4.1.2 BeanFactory和ApplicationContext的区别

4.1.3 ApplicationContext 接口的实现类

代码演示

// 创建容器对象,加载配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
//从容器获取对象
Object obj = ac.getBean("accountDao");
System.out.println(obj);

4.2 IOC中Bean标签和管理对象细节

4.2.1 Bean标签的对象获取: getBean方法

public class SpringIocTest {
    public static void main(String[] args) {
        //1.使用 ApplicationContext 接口,就是在获取 spring 容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        //2.根据 bean 的 id 获取对象
        AccountDao accountDao = (AccountDao) ac.getBean("accountDao");
        System.out.println(accountDao);
        accountDao.saveAccount();

        //方式2 : 根据字节码获取对象(常用)
        AccountDao accountDao2 = ac.getBean(AccountDao.class);
        System.out.println(accountDao2);
        accountDao2.saveAccount();
        
        
        //方式3 : (一个接口有多个实现类时)根据字节码与bean的id 进行确定获取指定Bean对象
        AccountDao accountDao3 = ac.getBean("accountDao", AccountDao.class);
        System.out.println(accountDao3);
        accountDao3.saveAccount();
    }
}

4.2.2 Bean标签的作用和属性

步骤1: 编写beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- bean 标签:用于配置让 spring 创建对象,并且存入 ioc 容器之中
        id 属性:对象的唯一标识。
        class 属性:指定要创建对象的全限定类名
    -->
    <bean id="accountDao"
          class="com.szz.dao.impl.AccountDaoImpl"
          scope="prototype"
          init-method="init"
          destroy-method="destroy"
    >

    </bean>
    <bean id="accountService" class="com.szz.service.impl.AccountServiceImpl"></bean>
</beans>
步骤2: 向实现类中添加init, destroy方法


import com.itheima.dao.AccountDao;

public class AccountDaoImpl implements AccountDao {
    @Override
    public void saveAccount() {
        System.out.println("Account save了");
    }

    @Override
    public void init() {
        System.out.println("AccountDao对象初始化");
    }

    @Override
    public void destroy() {
        System.out.println("AccountDao对象 销毁了");
    }
}

步骤3: 测试
/**
 * 测试类
 */
public class AccountTest {
    public static void main(String[] args) {
        //1. 获取Spring容器对象, 读取配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //2. 从Spring容器中, 获取指定ID 的对象
        AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
        //accountDao.saveAccount();
        System.out.println("accountDao = " + accountDao);

        //2. 从Spring容器中, 通过指定字节码文件 的方式 获取对象
        AccountDao accountDao2 = applicationContext.getBean(AccountDao.class);
        //accountDao2.saveAccount();
        System.out.println("accountDao2 = " + accountDao2);
    }
}

4.2.3 bean标签的生命周期

public class SpringIocTest {
    public static void main(String[] args) {
        //1.使用 ApplicationContext 接口,就是在获取 spring 容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        //2.根据 bean 的 id 获取对象
        AccountDao accountDao = (AccountDao) ac.getBean("accountDao");
        System.out.println(accountDao);
        accountDao.saveAccount();

        //方式2 : 根据字节码获取对象
        AccountDao accountDao2 = ac.getBean(AccountDao.class);
        System.out.println(accountDao2);
        accountDao2.saveAccount();

        ac.close();
    }
}

4.2.4 实例化bean的三种方式

方式1: Spring 使用默认无参构造函数(掌握)

在默认情况下, Spring会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败。

<bean id="accountService" class="com.szz.service.impl.AccountServiceImpl"/>
public class AccountTest {
    public static void main(String[] args) {
        //1. 获取Spring容器对象, 读取配置文件
        ApplicationContext  applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		//2. 从Spring容器中, 获取指定ID 的对象
  		AccountService accountService = (AccountService) applicationContext.getBean("accountService");
        //3.打印对象
        System.out.println("accountService = " + accountService);
        accountService.saveAccount();
    }
}
方式2: Spring 管理静态工厂-使用静态工厂的方法创建对象
public class StaticFactory {
    public static AccountService createAccountService(){
    	return new AccountServiceImpl();
    }
}

此种方式是 使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器

id 属性: 指定 bean 的 id,用于从容器中获取
class 属性: 指定静态工厂的全限定类名
factory-method 属性: 指定生产对象的静态方法 
<bean 
	id="accountService"
	class="com.itheima.factory.StaticFactory"
	factory-method="createAccountService">
</bean>
public class AccountTest {
    public static void main(String[] args) {
        //1. 获取Spring容器对象, 读取配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		//2. 从Spring容器中, 获取指定ID 的对象
  		AccountService accountService = (AccountService) applicationContext.getBean("accountService");
        //3.打印对象
        System.out.println("accountService = " + accountService);
        accountService.saveAccount();
    }
}
方式3: spring 管理实例工厂-使用实例工厂的方法创建对象

使用此工厂创建对象,必须现有工厂实例对象,再调用方法

public class InstanceFactory {
    public AccountService createAccountService(){
        return new AccountServiceImpl();
    }
}

此种方式是 先把工厂的创建交给 spring 来管理。然后在使用工厂的 bean 来调用里面的方法

factory-bean 属性: 用于指定实例工厂 bean 的 id。
factory-method 属性: 用于指定实例工厂中创建对象的方法
<bean id="instanceFactory" class="com.szz.factory.InstanceFactory"></bean>
<bean id="accountService"
      factory-bean="instanceFactory"
      factory-method="createAccountService">
</bean>
public class AccountTest {
    public static void main(String[] args) {
        //1. 获取Spring容器对象, 读取配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		//2. 从Spring容器中, 获取指定ID 的对象
  		AccountService accountService = (AccountService) applicationContext.getBean("accountService");
        //3.打印对象
        System.out.println("accountService = " + accountService);
        accountService.saveAccount();
    }
}

4.3 Spring的依赖注入(DI)

1. 什么是依赖注入

依赖注入(DI): Dependency Injection。就是让spring框架给Bean对象的属性进行赋值. 它是 spring 框架核心 ioc 的具体实现.

2. 使用构造函数方式 注入

顾名思义,就是使用类中的构造函数,给成员变量赋值。

注意,赋值的操作不是我们自己做的,而是通过配置的方式,让 spring 框架来为我们注入。具体代码如下

步骤1: 编写AccountServiceImpl
public class AccountServiceImpl implements AccountService {
    private String name;
    private Integer age;
    private Date birthday;
    
    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }
    
    @Override
    public void saveAccount() {
    	System.out.println(name+","+age+","+birthday);
    }
}
步骤2: 编写beans.xml

使用构造函数的方式,给pojo中的属性传值
要求:

涉及的标签:

编写beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="birthdayId" class="java.util.Date"></bean>
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <!--使用构造方法的方式1-->
        <!--<constructor-arg index="0" value="zhang3"></constructor-arg>-->
        <!--<constructor-arg index="1" value="25"></constructor-arg>-->
        <!--<constructor-arg index="2" ref="birthdayId"></constructor-arg>-->

        <!--使用构造方法的方式2-->
        <!--<constructor-arg type="java.lang.String" value="zhang3"></constructor-arg>-->
        <!--<constructor-arg type="java.lang.Integer" value="25"></constructor-arg>-->
        <!--<constructor-arg type="java.util.Date" ref="birthdayId"></constructor-arg>-->

        <!--使用构造方法的方式3 推荐-->
        <constructor-arg name="name" value="zhang3"></constructor-arg>
        <constructor-arg name="age" value="25"></constructor-arg>
        <constructor-arg name="birthday" ref="birthdayId"></constructor-arg>
    </bean>

</beans>
步骤3: 测试
public class AccontTest {
    public static void main(String[] args) {
        //获取ApplicationContext对象, Spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //获取Bean对象
        AccountService accountService = (AccountService) applicationContext.getBean("accountService");
        accountService.saveAccount();
    }
}

3. 使用set方法方式 注入

**顾名思义,就是在类中提供需要注入成员的 set 方法。**实际开发中,此种方式用的较多

具体代码如下

步骤1: 编写AccountServiceImpl
public class AccountServiceImpl implements AccountService {
    private String name;
    private Integer age;
    private Date birthday;
    
    public void setName(String name) {
    	this.name = name;
    }
    public void setAge(Integer age) {
    	this.age = age;
    }
    public void setBirthday(Date birthday) {
    	this.birthday = birthday;
    }
    
    @Override
    public void saveAccount() {
    	System.out.println(name+","+age+","+birthday);
    }
}
步骤2: 编写beans.xml

通过配置文件给 bean 中的属性传值:使用 set 方法的方式
涉及的标签:

<bean id="birthdayId" class="java.util.Date"></bean>
<bean id="accountService" class="com.szz.service.impl.AccountServiceImpl">
    <property name="name" value="lisi"></property>
    <property name="age" value="30"></property>
    <property name="birthday" ref="birthdayId"></property>
</bean>
步骤3: 测试
public class AccontTest {
    public static void main(String[] args) {
        //获取ApplicationContext对象, Spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //获取Bean对象
        AccountService accountService = (AccountService) applicationContext.getBean("accountService");
        accountService.saveAccount();
    }
}

4. 注入集合属性

顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。
我们这里介绍注入数组,List,Set,Map,Properties。具体代码如下

步骤1:编写AccountServiceImpl
public class AccountServiceImpl implements AccountService {
    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;
    private Properties myProps;
    
    public void setMyStrs(String[] myStrs) {
    	this.myStrs = myStrs;
    }
    public void setMyList(List<String> myList) {
    	this.myList = myList;
    }
    public void setMySet(Set<String> mySet) {
    	this.mySet = mySet;
    }
    public void setMyMap(Map<String, String> myMap) {
    	this.myMap = myMap;
    }
    public void setMyProps(Properties myProps) {
    	this.myProps = myProps;
    }

    @Override
    public void saveAccount() {
        System.out.println(Arrays.toString(myStrs));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        System.out.println(myProps);
    }
}
步骤2: 编写beans.xml

注入集合数据, 在注入集合数据时,只要结构相同,标签可以互换

<bean id="accountService" class="com.szz.service.impl.AccountServiceImpl">
    <!--数组-->
    <property name="myStrs">
        <array>
            <value>aaa</value>
            <value>bbb</value>
            <value>ccc</value>
        </array>
    </property>
    <!--list集合-->
    <property name="myList">
        <list>
            <value>javase</value>
            <value>mysql</value>
            <value>javaweb</value>
        </list>
    </property>
    <!--set集合-->
    <property name="mySet">
        <set>
            <value>北京</value>
            <value>上海</value>
            <value>南京</value>
        </set>
    </property>

    <!--map集合-->
    <property name="myMap">
        <map>
            <entry key="aaa" value="你好"></entry>
            <entry key="bbb" value="hello"></entry>
            <entry key="ccc" value="Hi"></entry>
        </map>
    </property>
    <!--properties集合-->
    <property name="myProps">
        <props>
            <prop key="111">哈哈</prop>
            <prop key="222">嘿嘿</prop>
            <prop key="333">呵呵</prop>
        </props>
    </property>
</bean>
</bean>
步骤3: 测试
public class AccontTest {
    public static void main(String[] args) {
        //获取ApplicationContext对象, Spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //获取Bean对象
        AccountService accountService = (AccountService) applicationContext.getBean("accountService");
        accountService.saveAccount();
    }
}

5 Spring整合Mybatis开发

5.1 整合思路

Spring和Mybatis都是框架,整合到底是Mybatis接管Spring,还是Spring接管Mybatis呢?

通过早期的学习,我们知道Mybatis框架是一个持久层ORM框架,而今天我们学习的Spring则是一个综合性的框架。所以整合是Mybatis往Spring上整合。就是让Spring框架接管Mybatis中的SqlSessionFactory工厂的创建,同时再通过读取mapper配置内容创建dao的代理实现类,并把他们都存入IoC容器。

Spring和Mybatis他们都有独立的配置文件,我们在整合时,有两种选择。第一种是保留两个框架的配置文件,第二种是只保留Spring的配置文件,把Mybatis相关的配置都写在Spring的配置文件中。这两种方式的结果是第二种看起来更为简洁明了。

5.2 操作步骤

在整合之前,我们先要分析整合步骤。我们的思路是,一个框架一个框架的去搭建环境,这样的好处是当出现问题能很快定位到哪里出了问题。

Mybatis框架搭建

0.数据库表

CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `money` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

0. pom文件

    <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>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

1. pojo

/**
 * 账户的实体类
 */
public class Account {

    private Integer id;
    private String name;
    private Double money;

 	//set,get等方法省略
}

2. 持久层接口

/**
 * 账户的持久层接口
 */
public interface AccountDao {

    /**
     * 更新账户
     */
    void update(Account account);

    /**
     * 根据名称查询账户
     */
    Account findByName(String name);
}

3. SQL映射文件

<?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.szz.dao.AccountDao">
    <!--配置根据名称查询-->
    <select id="findByName" resultType="account" parameterType="string">
        select * from account where name = #{name}
    </select>
    <!--配置更新-->
    <update id="update" parameterType="account">
        update account set name=#{name},money=#{money} where id=#{id}
    </update>
</mapper>

4. 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>
    <!--读取properties文件的为准-->
    <properties resource="jdbc.properties"></properties>
    <!--配置别名-->
    <typeAliases>
        <package name="com.itheima.pojo"></package>
    </typeAliases>
    <!--配置环境-->
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" 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>
            </dataSource>
        </environment>
    </environments>
    <!--配置映射-->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

5. mybatis框架测试

public class TestMybatis {
    public static void main(String[] args) throws IOException {
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        Account account = accountDao.findByName("老王");
        System.out.println("account = " + account);
    }
}

Spring框架搭建及整合Mybatis

6. 业务层接口及实现类

/**
 * 账户的业务层接口
 */
public interface AccountService {

    /**
     * 保存账户
     */
    void update(Account account);

    /**
     * 根据名称查询账户
     */
    Account findByName(String name);
}
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

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

    @Override
    public void update(Account account) {
        accountDao.update(account);
    }

    @Override
    public Account findByName(String name) {
        return accountDao.findByName(name);
    }
}

7. Spring核心配置文件配置Service层bean对象

<!--service层开始-->
<bean id="accountService" class="com.szz.service.impl.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"></property>
</bean>
<!--service层结束-->

8. Spring核心配置文件配置dao层bean对象

<!--dao层开始-->
<!--配置properties文件的位置-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

<!--配置数据源-->
<bean id="dataSource" 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="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!--注入数据源-->
    <property name="dataSource" ref="dataSource"></property>
    <!--配置别名-->
    <property name="typeAliasesPackage" value="com.szz.pojo"></property>
</bean>
<!--配置创建dao代理实现类的扫描器-->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.szz.dao"></property>
</bean>
<!--dao层结束-->

9. Spring框架整合Mybatis框架测试

public class TestSpring {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        AccountService accountService = ac.getBean(AccountService.class);
        Account account = accountService.findByName("热巴");
        System.out.println("account = " + account);
    }
}

->
<context:property-placeholder location=“classpath:jdbc.properties”></context:property-placeholder>

```

9. Spring框架整合Mybatis框架测试

public class TestSpring {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        AccountService accountService = ac.getBean(AccountService.class);
        Account account = accountService.findByName("热巴");
        System.out.println("account = " + account);
    }
}

标签:XML,01,对象,Spring,void,class,accountService,public
来源: https://blog.csdn.net/weixin_45727931/article/details/112752309