Spring学习笔记

spring简介

Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

目的:解决企业应用开发的复杂性

优点:

  • spring是一个开源免费的容器(框架)
  • spring是轻量级,非入侵式的框架
  • Spring是一个轻量级控制反转(IOC)面向切面(AOP)的容器框架。
  • 支持事务的处理,支持对框架的整合。

总结一句话: Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

导入依赖

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

spring组成

image-20210313190032064

扩展

image-20210313190204516
  • springBoot

    • 一个快速开发的脚手架。

    • 基于springBoot可以快速的开发单个微服务。

    • 约定大于配置。

  • springCloud

    • springCloud是基于springBoot实现的。

IOC控制反转

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency lnjection,DI)

IOC创建对象

实体类

@Data
public class User(){
  private String name;
}

user.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="hello" class="jxnuss.my.pojo.Hello">
     <property name="str" value="hello"></property>
    </bean>
    <bean id="userMysqlDao" class="jxnuss.my.dao.UserMysqlDaoImpl"></bean>
    <bean id="userOracleDao" class="jxnuss.my.dao.UserOracleDaoImpl"></bean>
    <bean id="userSqlServiceImpl" class="jxnuss.my.service.UserSqlServiceImpl">
     <property name="userSqlDao" ref="userOracleDao"></property>
    </bean>
</beans>

依赖注入

实体类

Address:
@Data
public class Address {
    private String address;
}
Student:
@Data
public class Student {
    private String name;
    private Address address;
    private String [] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private String work;
    private Properties info;
}

list,map,set,array,null注入

<?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 name="address" class="com.my.pojo.Address">
        <property name="address" value="北京西路"/>
     </bean>
    <bean name="student" class="com.my.pojo.Student">
        <!--String-->
        <property name="name" value="小明"/>
        <!--Address对象-->
        <property name="address" ref="address"/>
        <!--Array-->
        <property name="books">
            <array>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>
        <!--List-->
        <property name="hobbies">
            <list>
                <value>听歌</value>
                <value>打游戏</value>
                <value>敲代码</value>
            </list>
        </property>
        <!--Map-->
        <property name="card">
             <map>
                 <entry key="身份证" value="36089951998062505445"/>
                 <entry key="银行卡号" value="264562654585565256"/>
             </map>
        </property>
        <!--Set-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>王者荣耀</value>
                <value>COC</value>
            </set>
        </property>
        <!--null-->
        <property name="wife">
            <null/>
        </property>
        <!--""-->
        <property name="work" value=""/>
        <!--Properties-->
        <property name="info">
            <props>
                <prop key="学号">201826701005</prop>
                <prop key="学院">软件学院</prop>
                <prop key="性别">男</prop>
            </props>
        </property>
    </bean>
</beans>

测试

class StudentTest {
    @Test
    void test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) context.getBean("student");
        System.out.println("student = " + student);
    }
}
运行结果:
student = Student(
                  name=小明,
                  address=Address(address=北京西路),
                  books=[西游记, 水浒传, 三国演义], 
                  hobbies=[听歌, 打游戏, 敲代码], 
                  card={身份证=36089951998062505445, 银行卡号=264562654585565256},
                  games=[LOL, 王者荣耀, COC],
                  wife=null, 
                  work=,
                  info={学号=201826701005, 性别=男, 学院=软件学院})

Bean自动装配

在Spring 中,自动装配可以指定给每一个单独的 Bean,因此可以给一些Bean使用自动装配而其他的 Bean不使用自动装配。通过使用自动装配,开发人员可以减少指定属性的需要,从而节省一些属性设定的工作。使用Bean元素的autowire属性来指定 Bean定义的自动装配,共有5种模式,即 byName、byType、constructor、autodetect和 no。

byName模式

byName模式指的就是通过Bean 的属性名字进行自动装配。在Spring 的配置文档XML中,查找一个与将要装配的属性同样名字的 Bean。
在配置文档中,有一个id 为 HelloWorld 的 Bean被设置为通过 byName自动装配,HelloWorld.java包含一个date变量,Spring 就会查找一个叫做date 的 Bean定义,然后用它来设置date属性。使用byName模式的HelloWorld.java的示例代码如下:

@Data
public class HelloWorld{
    private String msg;
    private Date date;
}
<?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="HelloWorld" class="com.kuang.HelloWorld" autowire="byName">
        <property name="msg" value="小明"/>
    </bean>
    <bean id="date" class="java.util.Date"/>
</beans>

byType模式

byType模式指的就是如果XML中正好有一个与属性类型一样的 Bean,就自动装配这个属性。如果有多于一个这样的Bean,就抛出一个异常,指出可能不能对那个Bean使用byType的自动装配。

@Data
public class HelloWorld{
    private String msg;
    private Date date;
}
<?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="HelloWorld" class="com.kuang.HelloWorld" autowire="byType">
        <property name="msg" value="小明"/>
    </bean>
    <bean id="date11" class="java.util.Date"/>
</beans>

constructor模式

constructor模式指的就是根据构造函数的参数进行自动装配。在配置文档中,有一个id为HelloWorld 的 Bean 被设置为通过constructor自动装配,HelloWorld.java包含一个构造数方法,Spring就会根据构造函数的参数查找合适类型的Bean定义,然后用它来设置构造函数的参数的值。使用constructor模式的HelloWorld.java的示例代码如下:

@Data
public class HelloWorld{
    private String msg;
    private Date date;
    public HelloWorld(Date date){
        this.date=date;
    }
}
<?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="HelloWorld" class="com.kuang.HelloWorld" autowire="constructor">
        <property name="msg" value="小明"/>
    </bean>
    <bean id="date11" class="java.util.Date"/>
</beans>

autodetect模式

autodetect模式指的就是通过对 Bean检查类的内部来选择constructor或 byType。如果先找到constructor就用constructor;如果没有constructor,而找到 byType,就用byType。

no模式

no模式指的就是不使用自动装配。通过上面几节可以了解到,Bean 的引用必须通过ref元素定义。这是默认的配置,在很多企业级的应用环境中不鼓励使用自动装配模式,因为它对于Bean之间的参考依赖关系不清晰。

@Data
public class HelloWorld{
    private String msg;
    private Date date;
}
<?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="HelloWorld" class="com.kuang.HelloWorld" autowire="constructor">
        <property name="msg" value="小明"/>
        <property name="date" ref="date11"/> 
    </bean>
    <bean id="date11" class="java.util.Date"/>
</beans>

注解实现自动装配

导入context约束,开启注解支持

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
       <!-- 开启注解支持 -->
       <context:annotation-config/>
</beans>

@Autowired

@Autowired默认按照类型匹配注入bean,如果有多个类型相同的,再通过名称查找。

@Autowired搭配@Qualifier(“实现类名称”)表明注入的是哪一个实现类的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:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">
        <!-- 开启注解支持 -->
        <context:annotation-config/>
        <bean id="cat" class="com.xcz.pojo.Cat"/>
        <bean id="dog" class="com.xcz.pojo.Dog"/>
        <bean id="people" class="com.xcz.pojo.People"/>
    </beans>
    
  • 实体类

    @Data
    public class People {
        private String name;
        @Autowired
        private Cat cat;
        @Autowired
        private Dog dog;
        public void shout(){
            cat.shout();
            dog.shout();
        }
    }
    public class Dog {
        public void shout(){
            System.out.println("Dog....");
        }
    }
    public class Cat {
        public void shout(){
            System.out.println("Cat....");
        }
    }
    
  • 测试

    public class PeopleTest extends TestCase {
        public void testShout() {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            People people = context.getBean("people",People.class);
            people.shout();
        }
    结果:
        Cat....
        Dog....
    

@Qualifier

Qualifier ,读音:[ˈkwɒlɪfaɪə(r)] 的意思是合格者,通过这个标示,表明了哪个类才是我们所需要的;

    <bean id="cat" class="com.xcz.pojo.Cat"/>
    <bean id="dog" class="com.xcz.pojo.Dog"/>
    <bean id="dog11" class="com.xcz.pojo.Dog"/>
    <bean id="people" class="com.xcz.pojo.People"/>
public class People {
    private String name;
    @Autowired
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog11")
    private Dog dog;
    public void shout(){
        cat.shout();
        dog.shout();
    }
}

@Resource

@Resource默认按照名称匹配注入bean,而且可以使用name作为属性来确定实际注入的bean,如果按照名称无法找到就byType,byType有多个的话也会失败。

    <bean id="dog11" class="com.xcz.pojo.Dog"/>
    <bean id="dog22" class="com.xcz.pojo.Dog"/>
 @Resource(name = "dog22")
 private Dog dog;

有多个类型相同的bean时,@Autowired配合 @Qualifier(value = "...")来准确找到bean, @Resource(name = "...")来找bean

Spring注解开发

使用注解开发,要开启包扫描器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.xcz"/>
</beans>

@Component

把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>

@Component衍生注解

@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层

  • dao 【@Repository】
  • service【@Service】
  • controller【@Controller】

这4个注解意思一样,都是把类注册到spring容器中。

事务处理

什么是事务

事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败

  • 典型场景:银行转账

    lucy转账 100元 给 marye

    lucy 少100,mary多100

事务的4大特性

(1)原子性

(2) 一致性

(3)隔离性

(4)持久性

spring整合Mybatis

第一步:创建测试工程

第一步,首先在 IDEA 中新建一个名为【MybatisAndSpring】的 WebProject 工程:

img

然后在【src】中创建 4 个空包:

  • cn.wmyskxz.dao(放置 DAO 数据交互层处理类)
  • cn.wmyskxz.mapper(放置 Mapper 代理接口)
  • cn.wmyskxz.pojo(放置 Java 实体类)
  • cn.wmyskxz.test(放置测试类)

接着新建源文件夹【config】,用于放置各种资源配置文件:

  • 在【config / mybatis】下创建一个空的名为 “SqlMapConfig.xml” 的 MyBatis 全局配置文件
  • 在【config / spring】下创建一个空的名为 “applicationContext.xml” 的 Spring 资源配置文件
  • 在【config / sqlmap】下创建一个空的名为 “UserMapper.xml” 的 Mapper 映射文件。
  • 在【config】下创建两个 properties 属性文件,分别为 “db.properties” 和 “log4j.properties”,用于数据库连接和日志系统参数设置。

再在【web】文件夹下新建一个【WEB-INF】默认安全文件夹,并在其下创建一个【classes】和【lib】,并将项目的输出位置,改在【classes】下:

img

工程的完整初始结构如下:

img

第二步:引入依赖 jar 包

第二步,就是要准备项目的依赖 jar 包:

img

在【WEB-INF】文件夹下的【lib】文件夹中放置上面列举的 jar 包,然后添加依赖。

第三步:编写 Spring 配置文件

第三步,编写 Spring 的配置文件:

  • 加载数据库连接文件 “db.properties” 中的数据,建立数据源
  • 配置 sqlSessionFactory 会话工厂对象
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 加载配置文件 -->
    <context:property-placeholder location="db.properties"/>

    <!-- 配置数据源 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!-- sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 加载 MyBatis 的配置文件 -->
        <property name="configLocation" value="mybatis/SqlMapConfig.xml"/>
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
     <!-- SqlSessionTemplate -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
         <!-- 构造器注入 -->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
        <!-- 也可以这样写:<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/> -->        
    </bean>
</beans>
  • 头部的信息就是声明 xml 文档配置标签的规则的限制与规范。
  • “context:property-placeholder” 配置是用于读取工程中的静态属性文件,然后在其他配置中使用时,就可以采用 “${属性名}” 的方式获取该属性文件中的配置参数值。
  • 配置了一个名为 “dataSrouce” 的 bean 的信息,实际上是连接数据库的数据源。
  • 设置 sqlSessionFactory 的 bean 实现类为 MyBatis 与 Spring 整合 jar 包中的 SqlSessionFactoryBean 类,在其中只需要注入两个参数:一个是 MyBatis 的全局配置文件,一个是上面配置的数据源 bean

第四步:编写 MyBatis 配置文件

第四步,在【mybatis】包下编写 MyBatis 的全局配置文件 SqlMapConfig.xml :

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

    <!-- settings -->
    <settings>
        <!-- 打开延迟加载的开关 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 将积极加载改为消极加载(即按需加载) -->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!-- 打开全局缓存开关(二级缓存)默认值就是 true -->
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <!-- 别名定义 -->
    <typeAliases>
        <package name="cn.wmyskxz.pojo"/>
    </typeAliases>

    <!-- 加载映射文件 -->
    <mappers>
        <!-- 通过 resource 方法一次加载一个映射文件 -->
        <mapper resource="sqlmap/UserMapper.xml"/>
        <!-- 批量加载mapper -->
        <package name="cn.wmyskxz.mapper"/>
    </mappers>
</configuration>

在该配置文件中:

  • 通过 settings 配置了一些延迟加载和缓存的开关信息
  • typeAliases 中设置了一个 package 的别名扫描路径,在该路径下的 Java 实体类都可以拥有一个别名(即首字母小写的类名)
  • 在 mappers 配置中,使用 mapper 标签配置了即将要加载的 Mapper 映射文件的资源路径,当然也可以使用 package 标签,配置 mapper 代理接口所在的包名,以批量加载 mapper 代理对象。
  • 注意: 有了 Spring 托管数据源,在 MyBatis 配置文件中仅仅需要关注性能化配置。

第五步:编写 Mapper 以及其他配置文件

第五步,编写 Mapper 映射文件,这里依然定义 Mapper 映射文件的名字为 “UserMapper.xml” (与 SqlMapConfig.xml 中配置一致),为了测试效果,只配置了一个查询类 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="test">
    <select id="findUserById" parameterType="_int" resultType="user">
    SELECT * FROM USER WHERE id = #{id}
</select>
</mapper>

在该配置中,输出参数的映射为 “user” ,这是因为之前在 SqlMapConfig.xml 中配置了 “cn.wmyskxz.pojo” 包下的实体类使用别名(即首字母小写的类名),所以这里只需在 “cn.wmyskxz.pojo” 包下,创建 “finduserById” 对应的 Java 实体类 User:

package cn.wmyskxz.pojo;

import java.io.Serializable;

public class User implements Serializable {
    private int id;
    private String username;

    /* getter and setter */
}
  • 实现 Serializable 接口是为之后使用 Mapper 动态代理做准备,这里没有使用动态代理。

在数据库资源 “db.properties” 中配置了数据库的连接信息,以 “key=value” 的形式配置,String 正是使用 “${}” 获取其中 key 对应的 value 配置的:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root

另外日志配置和之前的配置一样,我就直接黏贴了:

# Global logging configuration
# 在开发环境下日志级别要设置成 DEBUG ,生产环境设为 INFO 或 ERROR
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

第六步:编写 Service 测试类

在 “cn.wmyskxz.test” 包下创建【UserServiceTest】测试类:

package cn.wmyskxz.test;

import cn.wmyskxz.dao.UserDAO;
import cn.wmyskxz.pojo.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceTest {

    private ApplicationContext applicationContext;

    // 在执行测试方法之前首先获取 Spring 配置文件对象
    // 注解@Before在执行本类所有测试方法之前先调用这个方法
    @Before
    public void setup() throws Exception {
        applicationContext = new
                ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
    }

    @Test
    public void testFindUserById() throws Exception {
        // 通过配置资源对象获取 userDAO 对象
        SqlSessionTemplate SqlSession = (SqlSessionTemplate) applicationContext.getBean("sqlSession");
        // 调用 UserMapper 的方法
        UserMapper userMapper = SqlSession.getMapper(UserMapper.class);
        User user userMapper.findUserById(1);
        // 输出用户信息
        System.out.println(user.getId() + ":" + user.getUsername());
    }
}

运行测试方法,输出结果如下:

img


动态代理 + 注解实现

上面的实例程序并没有使用 Mapper 动态代理和注解来完成,下面我们就来试试如何用动态代理和注解:

第一步:编写 UserQueryMapper

在【mapper】下新建一个【UserQueryMapper】代理接口,并使用注解:

package cn.wmyskxz.mapper;

import cn.wmyskxz.pojo.User;
import org.apache.ibatis.annotations.Select;

public interface UserQueryMapper {

    @Select("SELECT * FROM USER WHERE id = #{id}")
    public User findUserById(int id) throws Exception;
}
  • 注意: 在默认情况下,该 bean 的名字为 userQueryMapper(即首字母小写)

现在有了代理类,我们需要通知 Spring 在这里来扫描到该类,Mapper 扫描配置对象需要用专门的扫描器:

<!-- Mapper 扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 扫描 cn.wmyskxz.mapper 包下的组件 -->
    <property name="basePackage" value="cn.wmyskxz.mapper"/>
</bean>

第二步:编写测试类

这一次我们获取的不再是 userDAO 对象,而是定义的 Mapper 代理对象 userQueryMapper:

package cn.wmyskxz.test;

import cn.wmyskxz.mapper.UserQueryMapper;
import cn.wmyskxz.pojo.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceTest {

    private ApplicationContext applicationContext;

    // 在执行测试方法之前首先获取 Spring 配置文件对象
    // 注解@Before在执行本类所有测试方法之前先调用这个方法
    @Before
    public void setup() throws Exception {
        applicationContext = new
                ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
    }

    @Test
    public void testFindUserById() throws Exception {
        // 通过配置资源对象获取 userDAO 对象
        UserQueryMapper userQueryMapper = (UserQueryMapper) applicationContext.getBean("userQueryMapper");
        // 调用 UserDAO 的方法
        User user = userQueryMapper.findUserById(1);
        // 输出用户信息
        System.out.println(user.getId() + ":" + user.getUsername());
    }
}

运行测试方法,得到正确结果:

img

可以看到,查询结果和之前非 Mapper 代理的查询结果一样。

  • 原理: 在 applicationContext.xml 配置文件中配置的 mapper 批量扫描器类,会从 mapper 包中扫描出 Mapper 接口,自动创建代理对象并且在 Spring 容器中注入。自动扫描出来的 Mapper 的 bean 的 id 为 mapper 类名(首字母小写),所以这里获取的就是名为 “userQueryMapper” 的 mapper 代理对象。
posted @ 2021-03-31 10:40  xcz1998  阅读(90)  评论(0)    收藏  举报