Spring注解 && Spring注解整合MyBatis && Spring注解整合Junit


typora-root-url: img

一、使用xml文件整合MyBatis框架

在这里插入图片描述

这是MyBatis的核心配置文件,我们就对比着核心配置文件,将MyBatis整合进Spring中

首先我们需要先导入对应着的坐标

<dependency>  <!--实体类映射文件依然存在,所以需要-->
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>
<dependency>   <!--访问数据库-->
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
<dependency>  <!--spring框架的中的context坐标,用于读取配置文件-->
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.9.RELEASE</version>
</dependency>
<dependency>   <!--spring框架的中的jbdc坐标,用于处理数据库连接操作-->
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.1.9.RELEASE</version>
</dependency>
<dependency>  <!--连接池-->
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>
<dependency>  <!--MyBatis整合进Spring的实现坐标-->
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.0</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

起初我理解是,已经将MyBatis整合进Spring了,为什么还需要MyBatis的jar包?直接使用整合jar包不就好了吗?

因为我在这个测试中使用的配置文件的方式来映射Dao接口的(我将sql语句写在xml文件中,没有用注解)。所以任然需要MyBatis的jar包。

为什么将MyBatis整合进Spring需要MyBatis提供jar包?

因为Spring牛逼,市场占有份额高,所以由MyBatis提供,而且市面上这么多插件和框架,Spring的人得天天关注谁出新框架了之类得。

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
       https://www.springframework.org/schema/context/spring-context.xsd">

    <!--读取properties配置文件-->
    <context:property-placeholder  location="classpath:*.properties"/>

    <!--集成durid连接池  值是从配置文件中读取出来的-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <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>

    <!--配置核心配置文件-->
    <!--配置service作为spring的bean,注入dao  后面spring会自动帮我们注入-->
    <bean id="accountService" class="com.MyDemo.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>

    <!--spring整合mybatis后控制的创建连接用的对象-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--包扫描别名-->
        <property name="typeAliasesPackage" value="com.xiao.domain"/>
    </bean>

    <!--加载mybatis映射配置的扫描,将其作为spring的bean进行管理-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.xiao.dao"/>
    </bean>
</beans>

分块解释:

xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

因为读取配置文件,是归属另一块命名空间管理,所以需要引入新的约束

<context:property-placeholder  location="classpath:*.properties"/>

读取配置文件,classpath:*.properties 读取resources目录下所有properties文件,*是通配符

<!--集成durid连接池  值是从配置文件中读取出来的-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <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>

在原有的Mybatis中,提供有连接池,但是现在整合进Spring,连接池没了,所以需要我们自己配置。

将连接池这个类告诉Spring,它就会帮我们自动创建这个对象。

<!--spring整合mybatis后控制的创建连接用的对象-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!--包扫描别名-->
    <property name="typeAliasesPackage" value="com.xiao.domain"/>
</bean>

我们在使用MyBatis框架的时的操作步骤:

工厂构造类 —> 工厂类 —> sql会话对象 —> 根据接口和配置文件生成sql语句执行对象

最终我们要得到就是sql语句的执行对象。

//1.读取mybatis主配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.使用构建者创建SqlSessionFactory工厂
SqlSessionFactory factory = builder.build(in);
//4.获得sql会话对象
SqlSession sqlSession = factory.openSession(true);
//5.获得执行对象
UserDao userDao = sqlSession.getMapper(UserDao.class);

MyBatis提供将其整合进Spring的jar包

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.0</version>
</dependency>

在这里插入图片描述

由这个jar包的结构目录我们知道,我们现在可以直接获取SqlSession对象。通过这个类直接创建即可。

对比之前MyBatis使用配置文件方式创建SqlSession对象,配置文件中我们需要加载配置文件,定义数据库连接池,定义包的别名,定义实体类映射的配置文件。

在这里插入图片描述

通过查看这个类的方法结构我们知道,现在我们将这些原本使用配置文件设置的方式改为了set方法,那么我们就可以在spring中使用set注入,为SqlSession对象赋值。

那么我们还需要的实体类映射配置文件呢?

原本我们也可以使用set方法进行设置,但是MyBatis给了我们更优化的方法

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.xiao.dao"/>
</bean>

在这里插入图片描述

将加载实体类定义为了一个类,那么我们只需要通过bean标签配置之后,spring会帮助我们自动生成对象。

spring在看见MyBatis的整合之后

 <!--spring整合mybatis后控制的创建连接用的对象-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!--包扫描别名-->
    <property name="typeAliasesPackage" value="com.xiao.domain"/>
</bean>

<!--加载mybatis映射配置的扫描,将其作为spring的bean进行管理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.xiao.dao"/>
</bean>

会先创建出一个SqlSession对象,和实体类映射配置对象,SqlSession对实体类映射配置对象进行加工,产生了sql语句执行对象,然后进行分发,一看,咦,

<!--配置service作为spring的bean,注入dao  后面spring会自动帮我们注入-->
<bean id="accountService" class="com.xiao.service.impl.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"/>
</bean

你需要使用,那么我spring就将对应的sql语句执行对象注入进去。欧克,完美结束。

二、Spring注解开发

使用注解的形式替代xml配置,将繁杂的spring配置文件从工程中彻底消除掉,简化书写

在这里插入图片描述

对比注解和配置文件的方式:

1、使用配置的方式多一个配置文件,需要在java代码和配置文件之间相互切换

2、但是注解需要在源代码上进行修饰,如果我们使用第三方资源时,无法修改源代码,所以会增加一定工作量,但是这是注解的便利更多,所以是可以接受的。

调用注解管理的对象:

ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountService accountServiceImpl2 = (AccountService) ctx.getBean("AccountServiceImpl_2");
        accountServiceImpl2.save(new Account(3,"shaoting",2000));

我们new对象的方式和配置文件不一样了,但是调用都是一样的,都是使用getBean方法。

1、常用注解

<context:component-scan base-package="packageName"/>

在使用注解之前,我们需要先在配置文件声明。这样spring才会到指定目录下去扫描注解。

至于为什么使用了注解还需要配置文件,先慢慢来,后面会将配置文件全部移除掉。替换是有一个过程的。

说明:
◆ 在进行包所扫描时,会对配置的包及其子包中所有文件进行扫描
◆ 扫描过程是以文件夹递归迭代的形式进行的
◆ 扫描过程仅读取合法的java文件
◆ 扫描时仅读取spring可识别的注解
◆ 扫描结束后会将可识别的有效注解转化为spring对应的资源加入IoC容器

注意:
◆ 无论是注解格式还是XML配置格式,最终都是将资源加载到IoC容器中,差别仅仅是数据读取方式不同
◆ 从加载效率上来说注解优于XML配置文件(因为看见了注解就直接加载到容器中,使用配置,得先根据class属性找到对应的类,在将其加载到容器中)

1.1 bean的定义

替换bean标签的注解:@Component @Controller @Service @Repository

类型:类注解
位置:类定义上方
作用:设置该类为spring管理的bean

说明:
◆ @Controller、@Service 、@Repository是@Component的衍生注解,功能同@Component

@Controller、@Service 、@Repository是spring的一个规范,分别对应web控制层、业务层、数据层

实际上与@Component相同,四个都可以混着用,但是建议按照规范书写,不然容易引发同事矛盾。

@Service("AccountServiceImpl")
public class AccountServiceImpl implements AccountService {
}

名称:@Scope
类型:类注解
位置:类定义上方
作用:设置该类作为bean对应的scope属性

@Scope("prototype")
public class ClassName{}

相关属性
◆ value(默认):定义bean的作用域,默认为singleton

名称:@PostConstruct、@PreDestroy
类型:方法注解
位置:方法定义上方
作用:设置该类作为bean对应的生命周期方法

参考上面的那一张图吧。

2、注解加载第三方资源

我们的注解是加载类上面的,第三方资源的代码我们没有修改的权限,那么怎么通过注解的方式让spring帮我们管理对象呢?

使用工厂对象创建的方法。在配置文件中

<!--静态工厂创建bean-->
    <bean id="userService4" class="com.xiao.service.UserServiceFactory" factory-method="getService"/>

这句代码执行流程是:spring要给这个类创建对象,一看,有一个factory-method="getService"属性,spring就明白了,你原来是让我执行这个类的方法,不是创建这个类的对象,那么spring就去执行这个方法,结果得到另一个对象。那么spring就管理这个返回的对象

那么注解,我们也有对应的注解。所以我们通过工厂模式来加载第三方的资源

话不多说上代码:

在这里插入图片描述

首先必须给类加上注解,保证这个类被spring扫描到,spring进入这个类,看见@Bean注解,就会调用这个方法,将得到的对象与对应的id(bena注解括号里的值)管理起来,所以我们直接getBean对应id即可获取这个第三方的资源对象。

你说为什么不使用静态方法,让spring管理这个类就行了。后面要使用第三方资源直接通过类点调用就好了。

因为,首先多一层,控制肯定不方便,而且在属性注入的时候,我们直接使用对应id进行注入,难不成你要我还要再被注入的类中,再去点调用一次方法得到第三方资源对象,这肯定不合理。

3、属性注入

对比配置文件

<bean id="accountService" class="com.xiao.service.impl.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"/>
</bean>

再bean标签中使用property标签,而且对应的类必须要有set方法!

使用注解注入。

3.1 基本属性类型

在这里插入图片描述

直接在对应的属性上面写值,这只是一种格式,@Value中可以使用变量,通常和读取配置文件结合使用(后面讲)

那么set方法我也可以省略。

3.2 引用数据类型

名称:@Autowired、@Qualifier
类型:属性注解、方法注解
位置:属性定义上方,方法定义上方
作用:设置对应属性的对象或对方法进行引用类型传参

◆ @Autowired默认按类型装配,指定@Qualifier后可以指定自动装配的bean的id

@Autowired
private UserDao userDao;

在这里插入图片描述

名称:@Primary
类型:类注解
位置:类定义上方
作用:设置类对应的bean按类型装配时优先装配

@Autowired 自动属性注入,spring会自动识别。刚好你这里有一个类型是UserDao,如果没有id,但是只有一个UserDao的实现类,那么spring也会讲这个唯一的UserDao给你注入到对应的属性值中。

如果你有两个UserDao的实现类,但是其中一个id和你变量名匹配,那么spring会将id与变量匹配的UserDao注入对应的属性值中。

如果两个UserDao实现类,但是两个的id都不和变量匹配,那么会报错

如果两个UserDao实现类,但是两个的id都不和变量匹配,那么我们可以使用@Qualifier(“id值”),可以指定注入哪一个UserDao的实现类。

如果两个Use人Dao都没有指定id,使用@Autowired自动装配会报错,那么我们可以使用@Primary在两个UserDao的实现类中,谁有就先注入谁的,但是两者不同同时存在!

如果在系统更迭时,出现了三个UserDao的实现类,那么只能通过@Qualifier指定具体的id

3.3 加载properties配置文件的注解

名称:@PropertySource
类型:类注解
位置:类定义上方
作用:加载properties文件中的属性值

范例:

@PropertySource(value = "classpath:filename.properties")
public class ClassName {
    @Value("${propertiesAttributeName}")
    private String attributeName;
}

说明:
◆ 不支持*通配格式,一旦加载,所有spring控制的bean中均可使用对应属性值

◆ value(默认):设置加载的properties文件名
◆ ignoreResourceNotFound:如果资源未找到,是否忽略,默认为false

当你的配置文件都有,你可以在()里只写配置问价名,但是注意要是数组格式{1,2,3}

但是当你配置文件不存在会报错,如果想让有就加载没有就忽略的功能,那么加上 ignoreResourceNotFound=true,那么前面的数组必须对应value属性。

@PropertySource(value = {"classpath:filename.properties","abc.properties"},ignoreResourceNotFound=true)

结合之前基本类型的属性注入。就可以使用文件中的值,${} ,对应文件中的键

三、Spring纯注解开发

纯注解格式:

  • 名称:@Configuration、@ComponentScan

  • 类型:类注解

  • 位置:类定义上方

  • 作用:设置当前类为spring核心配置加载类

  • 范例:

    @Configuration
    @ComponentScan("scanPackageName")
    public class SpringConfigClassName{
    }
    

@Configuration 声明这是一个配置类,就不用去加载spring的配置文件了,

@ComponentScan(“scanPackageName”),作用是打开包扫描,去指定目录下扫描哪些类使用了spring注解。效果等于配置文件中的 <context:component-scan base-package=“packageName”/>

说明:
◆ 核心配合类用于替换spring核心配置文件,此类可以设置空的,不设置变量与属性
◆ bean扫描工作使用注解@ComponentScan替代

AnnotationConfigApplicationContext

加载纯注解格式上下文对象,需要使用AnnotationConfigApplicationContext

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

第三方bean配置与管理

名称:@Import
类型:类注解
位置:类定义上方
作用:导入第三方bean作为spring控制的资源
范例:

@Configuration
@Import(OtherClassName.class)
public class ClassName {
}

说明:
◆ @Import注解在同一个类上,仅允许添加一次,如果需要导入多个,使用数组的形式进行设定
◆ 在被导入的类中可以继续使用@Import导入其他资源(了解)
◆ @Bean所在的类可以使用导入的形式进入spring容器,无需声明为bean

之前我们的配置文件也是根据不同的模块对配置文件进行拆分,这个@Import就是带体配置文件的import标签的

四、使用纯注解整合MyBatis

在这里插入图片描述

我们只需要将对应部分换成注解就行了,其他的思想和思路和配置文件时一样的,只要你会配置文件整合,那么注解你就只需要多记忆几个注解。

首先我们制作一个主配置类,所以需要@Configuration申明这时一个著配置类,然后我们需要包扫描,所以需要@ConponentScan(“包路径”)

在实际开发中,一个外部资源,一个模块一个配置类,所以我们需要将其他配置类导入进来,@Import

@Configuration
@ConponentScan("com.test")
@Import({"JDBCConfig.class","MyBatisConfig.class"})
@PropertySource("classPath:jdbc.properties")
public class SpringConfig(){
    
}

JDBCConfig配置类

需要读取properties配置文件,所以需要@PropertySource,那么和xml配置文件一样,同意在主类上加

我们需要从配置文件中读取数据@Value

我们需要类似工厂模式的方法加载第三方资源,所以需要@Bean,因为Import导入了,所以类上面不需要@Component

public class JDBCConfig(){
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password; 
    
    @Bean("dataSource")
    public DataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

MyBatisConfig配置类

我们需要Sqlsession对象,所以使用工厂方法@Bean。反正第三方的资源,需要我们创建都对象才能使用的都使用@Bean注解工厂模式进行创建,因为源码我们无法进行修改。

public class MyBatisConfig(){
    @Bean
    public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setTypeAliasesPackage("com.xiao.domain");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }  
    
    //通过包扫描读取配置文件
    @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.xiao.dao");
        return msc;
    }
}

将SqlSession对象交有spring进行管理,显示MyBatis使用纯注解的方式就整合完毕了。

为什么MyBaits的Bean不用加id值,因为这是交给spring使用的,spring会根据类型自动识别,为什么上面JDBCConfig的Bean需要加id,因为这个类创建之后要给SqlSession对象使用,使用传参的方式,@Autowired自动注入到参数中。

使用

@Service("AccountServiceImpl_2")
public class AccountServiceImpl_2 implements AccountService {
    @Autowired
    private AccountDao accountDao;
    
    @Override
    public void save(Account account) {
        accountDao.save(account);
    }
    @Override
    public List<Account> findAll() {

        return accountDao.findAll();
    }
}

Sqlsession对象,根据实体类映射生成sql语句执行对象,生成之后交由spring管理,根据 @Autowired注解,自动将对应类型的sql语句对象注入到业务层中。

现在想一想框架。我们多了三个配置类。但是MyBatis的核心配置文件,实体类映射文件得了,但是数据层的接口得需要使用注解,这是一个非常要注意的地方。

五、Spring整合Junit

在这里插入图片描述

在这里插入图片描述

Spring接管Junit的运行权,使用Spring专用的Junit类加载器

因为我要使用自动注入,所以需要加载Spring配置类

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值