Spring 注解开发及框架整合

主要内容:

IOC/DI配置管理第三方bean
IOC/DI的注解开发
IOC/DI注解管理第三方bean
SpringMybatisJunit的整合开发

目录

1.IOC/DI配置管理第三方bean

1.1案例:数据源对象管理

1.1.1环境准备

1.1.2思路分析

1.1.3实现Druid管理

1.1.4小结

1.2加载properties文件

1.2.1 第三方bean属性优化

1.2.2读取单个属性

1.2.3加载properties小结

2.核心容器

2.1容器        

2.1.1容器的创建方式

2.1.2bean的三种获取方式

 2.1.3容器的层次结构

2.1.4BeanFactory的使用

2.1.5小结

2.2核心容器的总结

2.2.1容器相关

2.2.2bean相关

 2.2.3依赖注入相关

3.IOC/DI注解开发

3.1注解开发定义bean

3.2纯注解开发模式

3.3注解开发Bean作用范围与生命周期管理

3.3.1Bean的作用范围

3.3.2Bean的生命周期

3.4注解开发依赖注入

3.4.1注解实现按照类型注入

3.4.2注解实现按照名称注入

3.4.3简单数据类型注入

3.4.4注解读取properties配置文件

4.IOC/DI注解开发管理第三方bean

4.1注解开发管理第三方bean

4.3引入外部配置类

4.3.1使用包扫描引入(不推荐,阅读性差)

4.3.2使用@Import引入

4.4注解开发实现为第三方bean注入资源

4.4.1注入简单数据类型

4.4.2注入引用数据类型

5.注解开发总结

6.Spring整合

6.1Spring整合Mybatis思路分析

*6.1.2整合思路分析

6.2Spring整合Mybatis


1.IOC/DI配置管理第三方bean

1.1案例:数据源对象管理

数据源Druid(德鲁伊)C3P0对象进行管理

1.1.1环境准备

创建一个 Maven 项目
pom.xml 添加依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
resources 下添加 spring 的配置文件 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
            http://www.springframework.org/schema/context/spring-context.xsd
            ">
</beans>
编写一个运行类 App

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

1.1.2思路分析

需求 : 使用 Spring IOC 容器来管理 Druid 连接池对象
1. 使用第三方的技术,需要在 pom.xml 添加依赖
2. 在配置文件中将【第三方的类】制作成一个 bean ,让 IOC 容器进行管理
3. 数据库连接需要基础的四要素 驱动 连接 用户名 密码 ,【如何注入】到对应的 bean
4. IOC 容器中获取对应的 bean 对象,将其打印到控制台查看结果

1.1.3实现Druid管理

步骤1:导入druid的依赖
pom.xml 中添加依赖
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
步骤 2: 配置第三方 bean
applicationContext.xml 配置文件中添加 DruidDataSource 的配置
<?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
            ">
<!--    管理DruidDataSource对象-->
        <bean class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
</beans>
说明 :
class声明操作对象

driverClassName: 数据库驱动
url: 数据库连接地址
username: 数据库连接用户名
password: 数据库连接密码
数据库连接的四要素要和自己使用的数据库信息一致。

 步骤3:IOC容器中获取对应的bean对象

package com.itheima;

import com.itheima.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        DataSource dataSource = (DataSource) ctx.getBean("dataSource");
        System.out.println(dataSource);
    }
}
步骤 4: 运行程序
打印如下结果 : 说明第三方 bean 对象已经被 spring IOC 容器进行管理

第三方的类指的是什么?
DruidDataSource
如何注入数据库连接四要素?
setter 注入

1.1.4小结

首先在pom.xml中导入druid的坐标,然后对druid进行配置(在applicationContext中配置),然后使用ClassPathXmlApplicationContext方法中加载配置文件,new出一个IOC容器,使用容器中的getBean方法,得到dataSource对象。

1.2加载properties文件

有利于对数据源后期的维护,只需要在properties中修改常量。

1.2.1 第三方bean属性优化

需求 : 将数据库连接四要素提取到 properties 配置文件, spring 来加载配置信息并使用这些信息
来完成属性注入。
1. resources 下创建一个 jdbc.properties( 文件的名称可以任意 )

2.将数据库连接四要素配置到配置文件中

3. Spring 的配置文件中加载 properties 文件
4. 使用加载到的值实现属性注入
步骤1:准备properties配置文件
resources 下创建一个 jdbc.properties 文件 , 并添加对应的属性键值对
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=root
步骤2:开启context 命名空间
applicationContext.xml 中开 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
            ">

注意:配置xmlns:context和xsi:schemaLocation。

步骤3:加载properties配置文件
在配置文件中使用 context 命名空间下的标签来加载 properties 配置文件
<context:property-placeholder location="jdbc.properties"/>
步骤4:完成属性注入
使用 ${key} 来读取 properties 配置文件中的内容并完成属性注入
    <bean 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>

1.2.2读取单个属性

需求 : properties 配置文件中读取 key name 的值,并将其注入到 BookDao 中并在 save 方法中
进行打印。
1. 在项目中添加 BookDao BookDaoImpl
2. BookDaoImpl 添加一个 name 属性并提供 setter 方法
3. jdbc.properties 中添加数据注入到 bookDao 中打印方便查询结果
4. applicationContext.xml 添加配置完成配置文件加载、属性注入 (${key})
applicationContext.xml 添加配置, bean 的配置管理 读取外部 properties 依赖注入 :
<!--    1.开启context命名空间-->
<!--    2.使用context空间加载properties文件-->
<!--    <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/> -->
<!--    由于某一些变量名会跟系统产生冲突,比如username为电脑的默认值,使用system-properties-mode="NEVER"属性可以防止properties文件中的username覆盖电脑系统的username-->
<!--    <context:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>-->
<!--    加载的配置文件可以是多个,用空格隔开-->
<!--    classpath:*.properties  :   设置加载当前工程类路径中的所有properties文件-->
<!--    system-properties-mode属性:是否加载系统属性-->
<!--        <context:property-placeholder location="*.properties" system-properties-mode="NEVER"/>-->

    <!--classpath*:*.properties  :  设置加载当前工程类路径和当前工程所依赖的所有jar包中的所有properties文件-->
    <context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>

<!--    3.使用属性占位符${}读取properties文件中的属性-->
<!--    说明:idea自动识别${}加载的属性值,需要手工点击才可以查阅原始书写格式-->
    <bean 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>
        <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <property name="name" value="${username}"/>
    </bean>

将properties中的属性注入到druid的bean对象中,然后使用DI依赖注入,将单一的属性注入到bookDaoImpl类中,该类使用setter注入,最后输出。

1.2.3加载properties小结

如何开启context命名空间
如何加载properties配置文件
<context:property-placeholder location="" system-properties-mode="NEVER"/>

如何在applicationContext.xml引入properties配置文件中的值

@{key}

2.核心容器

如何创建容器 ?
创建好容器后,如何从容器中获取 bean 对象 ?
容器类的层次结构是什么 ?
BeanFactory 是什么 ?

2.1容器        

2.1.1容器的创建方式

方式一:类路径下的XML配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

方式二:文件系统下的XML配置文件

ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\workspace
\\spring\\spring_10_container\\s rc\\main\\resources\\applicationContext.xml");

2.1.2bean的三种获取方式

方式一
BookDao bookDao = (BookDao) ctx.getBean("bookDao");

该方式需要进行强制转换

方式二:
BookDao bookDao = ctx.getBean("bookDao",BookDao.class);

该方式不需要强制转换,但需要在参数中声明类的类型

方式三:

BookDao bookDao = ctx.getBean(BookDao.class);
这种方式就类似我们之前所学习依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个。

 2.1.3容器的层次结构

(1)IDEA中双击shift ,输入BeanFactory
(2)点击进入BeanFactory类,ctrl+h,就能查看到如下结构的层次关系

2.1.4BeanFactory的使用

使用 BeanFactory 来创建 IOC 容器的具体实现方式为 :
package com.itheima;

import com.itheima.dao.BookDao;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
//初始化BeanFactory
public class AppForBeanFactory {
    public static void main(String[] args) {
        Resource resources = new ClassPathResource("applicationContext.xml");
        BeanFactory bf = new XmlBeanFactory(resources);
        BookDao bookDao = bf.getBean(BookDao.class);
        bookDao.save();
    }
}

BeanFactory和ApplicationContext创建IOC容器的区别:

BeanFactory 是延迟加载,只有在获取 bean 对象的时候才会去创建
ApplicationContext 是立即加载,容器加载的时候就会创建 bean 对象
ApplicationContext 要想成为延迟加载,只需要按照如下方式进行配置

2.1.5小结

容器创建的两种方式
ClassPathXmlApplicationContext[ 掌握 ]
FileSystemXmlApplicationContext[ 知道即可 ]
获取Bean的三种方式
getBean(" 名称 "): 需要类型转换
getBean(" 名称 ", 类型 .class): 多了一个参数
getBean( 类型 .class): 容器中不能有多个该类的 bean 对象
上述三种方式,各有各的优缺点,用哪个都可以。
容器类层次结构
只需要知晓容器的最上级的父接口为 BeanFactory 即可
BeanFactory
使用 BeanFactory 创建的容器是延迟加载
使用 ApplicationContext 创建的容器是立即加载
具体 BeanFactory 如何创建只需要了解即可。

2.2核心容器的总结

2.2.1容器相关

BeanFactory IoC 容器的顶层接口,初始化 BeanFactory 对象时,加载的 bean 延迟加载
ApplicationContext 接口是 Spring 容器的核心接口,初始化时 bean 立即加载
ApplicationContext 接口提供基础的 bean 操作相关方法,通过其他接口扩展其功能
ApplicationContext 接口常用初始化类:
ClassPathXmlApplicationContext( 常用 )
FileSystemXmlApplicationContext

2.2.2bean相关

 2.2.3依赖注入相关

3.IOC/DI注解开发

Spring 对注解支持的版本历程 :
2.0 版开始支持注解
2.5 版注解功能趋于完善
3.0 版支持纯注解开发
注解开发定义 bean 纯注解开发
注解开发定义 bean 用的是 2.5 版提供的注解,纯注解开发用的是 3.0 版提供的注解。

3.1注解开发定义bean

步骤 1: 删除原 XML 配置
将配置文件中的 <bean> 标签删除掉
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
步骤 2:Dao 上添加注解
BookDaoImpl 类上添加 @Component 注解
@Component("bookDao") 
public class BookDaoImpl implements BookDao { 
    public void save() { 
    System.out.println("book dao save ..." ); 
    }
}
注意 :@Component 注解不可以添加在接口上,因为接口是无法创建对象的。
XML 与注解配置的对应关系 :

 步骤3:配置Spring的注解包扫描

为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.itheima"/>

</beans>
说明 :
component-scan
component: 组件 ,Spring 将管理的 bean 视作自己的一个组件
scan: 扫描
base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。
包路径越多 [ :com.itheima.dao.impl] ,扫描的范围越小速度越快
包路径越少 [ :com.itheima], 扫描的范围越大速度越慢
一般扫描到项目的组织名称即 Maven groupId [ :com.itheima] 即可。
步骤 4 :运行程序
运行 App 类查看打印结果

步骤5:Service上添加注解

BookServiceImpl类上也添加@Component交给Spring框架管理

@Service
public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

步骤6:运行程序

App类中,从IOC容器中获取BookServiceImpl对应的bean对象,打印

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        //按类型获取bean
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}
说明 :
BookServiceImpl 类没有起名称,所以在 App 中是按照类型来获取 bean 对象
@Component 注解如果不起名称,会有一个默认值就是 当前类名首字母小写 ,所以也可以按照名 获取,如
BookService bookService = (BookService)ctx.getBean("bookServiceImpl"); System.out.println(bookService);
对于 @Component 注解,还衍生出了其他三个注解 @Controller、@Service、@Repository

3.2纯注解开发模式

 

@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中

将配置文件 applicationContext.xml 删除掉,使用类来替换。
步骤 1: 创建配置类
创建一个配置类 SpringConfig
public class SpringConfig { }
步骤 2: 标识该类为配置类
在配置类上添加 @Configuration 注解,将其标识为一个配置类 , 替换 applicationContext.xml
@Configuration 
public class SpringConfig { }
步骤 3: 用注解替换包扫描配置
在配置类上添加包扫描注解 @ComponentScan 替换 <context:component - scan base - package=""/>
@Configuration 
@ComponentScan("com.itheima") 
public class SpringConfig { }
步骤 4: 创建运行类并执行
创建一个新的运行类 AppForAnnotation
public class AppForAnnotation {
    public static void main(String[] args) {
        //AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        //按类型获取bean
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

纯注解开发总结:

Java 类替换 Spring 核心配置文件

@Configuration注解用于设定当前类为配置类

@ComponentScan 注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式
@ComponentScan({com.itheima.service","com.itheima.dao"})
读取 Spring 核心配置文件初始化容器对象切换为读取 Java 配置类初始化容器对象
//加载配置文件初始化容器 
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //加载配置类初始化容器 
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
记住@Component、@Controller、@Service、@Repository这四个注解
applicationContext.xml中<context:component-san/>的作用是指定扫描包路径,注解为
@ComponentScan
@Configuration标识该类为配置类,使用类替换applicationContext.xml文件
ClassPathXmlApplicationContext是加载XML配置文件
AnnotationConfigApplicationContext是加载配置类

3.3注解开发Bean作用范围与生命周期管理

3.3.1Bean的作用范围

3.3.2Bean的生命周期

如何对方法进行标识,哪个是初始化方法,哪个是销毁方法?
只需要在对应的方法上添加 @PostConstruct(在构造之后) @PreDestroy(在销毁之前) 注解即可。
package com.itheima.dao.impl;

import com.itheima.dao.BookDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Repository
//@Scope设置bean的作用范围
@Scope("singleton")
public class BookDaoImpl implements BookDao {

    public void save() {
        System.out.println("book dao save ...");
    }
    //@PostConstruct设置bean的初始化方法
    @PostConstruct
    public void init() {
        System.out.println("init ...");
    }
    //@PreDestroy设置bean的销毁方法
    @PreDestroy
    public void destroy() {
        System.out.println("destroy ...");
    }

}
注意 :@PostConstruct @PreDestroy 注解如果找不到,需要导入下面的 jar

找不到的原因是,从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包 中。

3.4注解开发依赖注入

Spring 为了使用注解简化开发,并没有提供 构造函数注入 setter 注入 对应的注解,只提供了自动
装配的注解实现。

3.4.1注解实现按照类型注入

(1) BookServiceImpl 类的 bookDao 属性上添加 @Autowired 注解
@Service
public class BookServiceImpl implements BookService{
    @Autowired
    private BookDao bookDao;

    public void save(){
        System.out.println("book service ..");
        bookDao.save();
    }
}
注意 :
@Autowired 可以写在属性上,也可也写在 setter 方法上,最简单的处理方式是 写在属性上并将
setter 方法删除掉
为什么setter方法可以删除呢?
自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
普通反射只能获取 public 修饰的内容
暴力反射除了获取 public 修饰的内容还可以获取 private 修改的内容
所以此处无需提供 setter 方法
@Autowired是按照类型注入,那么对应BookDao接口如果有多个实现类,比如添加
BookDaoImpl2
此时需要使用 按名称注入 ,即给每一个实体类创建对象。

3.4.2注解实现按照名称注入

当根据类型在容器中找到多个 bean, 注入参数的属性名又和容器中 bean 的名称不一致,这个时候该
如何解决,就需要使用到 @Qualifier来指定注入哪个名称的bean 对象
package com.itheima.service.impl;

import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl implements BookService{
    @Autowired
    @Qualifier("bookDao1")
    private BookDao bookDao;

    public void save(){
        System.out.println("book service ..");
        bookDao.save();
    }
}
@Qualifier 注解后的值就是需要注入的 bean 的名称。
注意 :@Qualifier 不能独立使用,必须和 @Autowired 一起使用

3.4.3简单数据类型注入

数据类型换了,对应的注解也要跟着换,这次使用 @Value 注解,将值写入注解的参数中就行了
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    //@Value:注入简单类型(无需提供set方法)
    @Value("itheima")
    private String name;

    public void save() {
        System.out.println("book dao save ..." + name);
    }
注意数据格式要匹配,如将 "abc" 注入给 int 值,这样程序就会报错。

3.4.4注解读取properties配置文件

@Value 一般会被用在从 properties 配置文件中读取内容进行使用,具体如何实现 ?
步骤 1 resource 下准备 properties 文件
jdbc.properties
name=itheima888
步骤 2: 使用注解加载 properties 配置文件
在配置类上添加 @PropertySource 注解
@Configuration //定义该类为配置类
@ComponentScan("com.itheima") //从com.itheima文件开始扫描
@PropertySource("jdbc.properties") //定义jdbc.properties为配置文件,可以使用value进行读取
public class SpringConfig { }
步骤 3 :使用 @Value 读取配置文件中的内容
@Repository("bookDao")//使用注解说明该类是一个bean,名称为bookDao
public class BookDaoImpl implements BookDao {
    //@Value:注入简单类型(无需提供set方法)
    @Value("${name}")
    private String name;

    public void save() {
        System.out.println("book dao save ..." + name);
    }
}
步骤4:运行程序
运行 App 类,查看运行结果,说明配置文件中的内容已经被加载到
注意 :
如果读取的 properties 配置文件有多个,可以使用 @PropertySource 的属性来指定多个
@PropertySource({"jdbc.properties","xxx.properties"})
@PropertySource 注解属性中不支持使用通配符 * , 运行会报错
@PropertySource({"*.properties"})
@PropertySource 注解属性中可以把 classpath: 加上 , 代表从当前项目的根路径找文件
 @PropertySource({"classpath:jdbc.properties"})

4.IOC/DI注解开发管理第三方bean

之前我们是用xml管理第三方bean,现在我们使用注解来管理第三方bean。

4.1注解开发管理第三方bean

步骤 1: 导入对应的 jar
<dependency> 
    <groupId>com.alibaba</groupId> 
    <artifactId>druid</artifactId> 
    <version>1.1.16</version> 
</dependency>
步骤 2: 在配置类中添加一个方法
注意该方法的返回值就是要创建的 Bean 对象类型
@Configuration
public class SpringConfig {
    public DataSource dataSource(){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
步骤3: 在方法上添加 @Bean 注解
@Bean 注解的作用是将方法的返回值制作为 Spring 管理的一个 bean 对象

 

@Configuration
public class SpringConfig {
    @Bean
    public DataSource dataSource(){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
注意 : 不能使用 DataSource ds = new DruidDataSource()
因为 DataSource 接口中没有对应的 setter 方法来设置属性。
步骤 4: IOC 容器中获取对象并打印
package com.itheima;

import com.itheima.config.SpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.sql.DataSource;

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}
至此使用 @Bean 来管理第三方 bean 的案例就已经完成。
如果有多个 bean 要被 Spring 管理,直接在配置类中多些几个方法,方法上添加 @Bean 注解即可。

4.3引入外部配置类

对于数据源的 bean, 我们新建一个 JdbcConfig 配置类,并把数据源配置到该类下。

4.3.1使用包扫描引入(不推荐,阅读性差)

步骤 1: Spring 的配置类上添加包扫描
@Configuration
@ComponentScan("com.itheima.config")
public class SpringConfig(){
}
步骤 2: JdbcConfig 上添加配置注解
JdbcConfig 类要放入到 com.itheima.config 包下,需要被 Spring 的配置类扫描到即可
​@Configuration
public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

4.3.2使用@Import引入

在SpringConfig类中使用@Import注解,并且声明导入包的字节码文件。

Spring 配置类中引入
@Configuration
//@ComponentScan("com.itheima")
//@Import:导入配置信息
@Import({JdbcConfig.class})
public class SpringConfig {
}
注意 :
扫描注解可以移除
@Import 参数需要的是一个数组,可以引入多个配置类。
@Import 注解在配置类中只能写一次,下面的方式是 不允许的

4.4注解开发实现为第三方bean注入资源

在使用 @Bean 创建 bean 对象的时候,如果方法在创建的过程中需要其他资源该怎么办 ?
这些资源会有两大类,分别是 简单数据类型 引用数据类型

4.4.1注入简单数据类型

将上面JdbcConfig类中为连接对象设置的参数使用properties进行配置。
步骤1:类中提供四个属性
public class JdbcConfig {
    //1.定义一个方法获得要管理的对象
    private String driver;
    private String url;
    private String userName;
    private String password;
    //2.添加@Bean,表示当前方法的返回值是一个bean
    //@Bean修饰的方法,形参根据类型自动装配
    @Bean
    public DataSource dataSource(){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
步骤2:使用@Value注解引入值
public class JdbcConfig {
    //1.定义一个方法获得要管理的对象
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring_db")
    private String url;
    @Value("root")
    private String userName;
    @Value("root")
    private String password;
    //2.添加@Bean,表示当前方法的返回值是一个bean
    //@Bean修饰的方法,形参根据类型自动装配
    @Bean
    public DataSource dataSource(){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
现在的数据库连接四要素还是写在代码中,需要做的是将这些内容提取到jdbc.properties配置文件,该如何实现?

resources 目录下添加 jdbc.properties
配置文件中提供四个键值对分别是数据库的四要素
使用 @PropertySource 加载 jdbc.properties 配置文件
修改 @Value 注解属性的值,将其修改为 ${key} key 就是键值对中的键的值

4.4.2注入引用数据类型

步骤1:在SpringConfig中扫描BookDao
扫描的目的是让 Spring 能管理到 BookDao, 也就是说要让 IOC 容器中有一个 bookDao 对象
@Configuration 
@ComponentScan("com.itheima.dao") 
@Import({JdbcConfig.class}) 
public class SpringConfig { }
步骤2:在JdbcConfig类的方法上添加参数
    @Bean
    public DataSource dataSource(BookDao bookDao){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
引用类型注入只需要为 bean 定义方法设置形参即可,容器会根据类型自动装配对象。

5.注解开发总结

6.Spring整合

 

 

6.1Spring整合Mybatis思路分析

步骤1:准备数据库表

Mybatis是来操作数据库表,所以先创建一个数据库及表

CREATE DATABASE spring_db CHARACTER SET utf8;

USE spring_db;

CREATE TABLE tbl_account(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(35),
money DOUBLE
);
步骤 2: 创建项目导入 jar
项目的 pom.xml 添加相关依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
    </dependencies>
步骤 3: 根据表创建模型类
package com.itheima.domain;


import java.io.Serializable;

public class Account implements Serializable {

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

    public Integer getId() {
        return id;
    }

    public void setId(Integer 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 +
                '}';
    }
}
步骤 4: 创建 Dao 接口
package com.itheima.dao;

import com.itheima.domain.Account;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

public interface AccountDao {

    @Insert("insert into tbl_account(name,money)values(#{name},#{money})")
    void save(Account account);

    @Delete("delete from tbl_account where id = #{id} ")
    void delete(Integer id);

    @Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ")
    void update(Account account);

    @Select("select * from tbl_account")
    List<Account> findAll();

    @Select("select * from tbl_account where id = #{id} ")
    Account findById(Integer id);
}
步骤 5: 创建 Service 接口和实现类
package com.itheima.service;

import com.itheima.domain.Account;

import java.util.List;

public interface AccountService {

    void save(Account account);

    void delete(Integer id);

    void update(Account account);

    List<Account> findAll();

    Account findById(Integer id);

}
package com.itheima.service.impl;

import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    public void save(Account account) {
        accountDao.save(account);
    }

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

    public void delete(Integer id) {
        accountDao.delete(id);
    }

    public Account findById(Integer id) {
        return accountDao.findById(id);
    }

    public List<Account> findAll() {
        return accountDao.findAll();
    }
}
步骤 6: 添加 jdbc.properties 文件
resources 目录下添加,用于配置数据库连接四要素
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false
jdbc.username=root
jdbc.password=root
useSSL: 关闭 MySQL SSL 连接
步骤 7: 添加 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.domain"/>
    </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>
步骤 8: 编写应用程序
import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class App {
    public static void main(String[] args) throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 2. 加载SqlMapConfig.xml配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml.bak");
        // 3. 创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        // 4. 获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 5. 执行SqlSession对象执行查询,获取结果User
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);

        Account ac = accountDao.findById(2);
        System.out.println(ac);

        // 6. 释放资源
        sqlSession.close();
    }
}
步骤 9: 运行程序

*6.1.2整合思路分析

Mybatis 的基础环境我们已经准备好了,接下来就得分析下在上述的内容中,哪些对象可以交给
Spring 来管理 ?
Mybatis程序核心对象分析

 从图中可以获取到,真正需要交给Spring管理的是SqlSessionFactory

整合 Mybatis ,就是将 Mybatis 用到的内容交给 Spring 管理,分析下配置文件

 

说明 :
第一行读取外部 properties 配置文件, Spring 有提供具体的解决方案 @PropertySource ,
要交给 Spring
第二行起别名包扫描,为 SqlSessionFactory 服务的,需要交给 Spring
第三行主要用于做连接池, Spring 之前我们已经整合了 Druid 连接池,这块也需要交给
Spring
前面三行一起都是为了创建 SqlSession 对象用的,那么用 Spring 管理 SqlSession 对象吗 ?
回忆下 SqlSession 是由 SqlSessionFactory 创建出来的,所以只需要将
SqlSessionFactory 交给 Spring 管理即可。
第四行是 Mapper 接口和映射文件 [ 如果使用注解就没有该映射文件 ] ,这个是在获取到
SqlSession 以后执行具体操作的时候用,所以它和 SqlSessionFactory 创建的时机都不在
同一个时间,可能需要单独管理。

6.2Spring整合Mybatis

前面我们已经分析了 Spring Mybatis 的整合,大体需要做两件事,
第一件事是:Spring要管理MyBatis中的SqlSessionFactory
第二件事是:Spring要管理Mapper接口的扫描
具体该如何实现,具体的步骤为 :
步骤 1: 项目中导入整合需要的 jar

    <dependency>
    <!--Spring操作数据库需要该jar包-->
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>

    <dependency>
    <!--
        Spring与Mybatis整合的jar包
        这个jar包mybatis在前面,是mybatis提供的
    -->
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.0</version>
    </dependency>
步骤 2: 创建 Spring 的主配置类
//配置类注解
@Configuration

//包扫描,主要扫描的是项目中的AccountServiceImpl类
@ComponentScan("com.itheima")
public class SpringConfig {
}
步骤 3: 创建数据源的配置类
在配置类中完成数据源的创建
package com.itheima.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;


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
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
步骤 4: 主配置类中读 properties 并引入数据源配置类
@Configuration
@ComponentScan("com.itheima")
//@PropertySource:加载类路径jdbc.properties文件
@PropertySource("classpath:jdbc.properties")
@Import(JdbcConfig.class)
public class SpringConfig {
}
步骤 5: 创建 Mybatis 配置类并配置 SqlSessionFactory
package com.itheima.config;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class MybatisConfig {
    //定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setTypeAliasesPackage("com.itheima.domain");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }
    //定义bean,返回MapperScannerConfigurer对象
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }
}



说明 :
使用 SqlSessionFactoryBean 封装 SqlSessionFactory 需要的环境信息

 

SqlSessionFactoryBean 是前面我们讲解 FactoryBean 的一个子类,在该类中将
SqlSessionFactory 的创建进行了封装,简化对象的创建,我们只需要将其需要的内容设置
即可。
方法中有一个参数为 dataSource, 当前 Spring 容器中已经创建了 Druid 数据源,类型刚好是
DataSource 类型,此时在初始化 SqlSessionFactoryBean 这个对象的时候,发现需要使用
DataSource 对象,而容器中刚好有这么一个对象,就自动加载了 DruidDataSource 对象。
使用 MapperScannerConfigurer 加载 Dao 接口,创建代理对象保存到 IOC 容器中

 

这个 MapperScannerConfigurer 对象也是 MyBatis 提供的专用于整合的 jar 包中的类,用来
处理原始配置文件中的 mappers 相关配置,加载数据层的 Mapper 接口类
MapperScannerConfigurer 有一个核心属性 basePackage ,就是用来设置所扫描的包路径
步骤 6: 主配置类中引入 Mybatis 配置类
@Configuration
@ComponentScan("com.itheima")
//@PropertySource:加载类路径jdbc.properties文件
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
}
步骤 7: 编写运行类
在运行类中,从 IOC 容器中获取 Service 对象,调用方法获取结果
import com.itheima.config.SpringConfig;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App2 {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

        AccountService accountService = ctx.getBean(AccountService.class);

        Account ac = accountService.findById(1);
        System.out.println(ac);
    }
}
步骤 8: 运行程序

 支持SpringMybatis的整合就已经完成了,其中主要用到的两个类分别是:

SqlSessionFactoryBean
MapperScannerConfigurer
6.3Spring整合Junit
整合 Junit 与整合 Druid MyBatis 差异比较大,为什么呢? Junit 是一个搞单元测试用的工具,它
不是我们程序的主体,也不会参加最终程序的运行,从作用上来说就和之前的东西不一样,它不是
做功能的,看做是一个辅助工具就可以了。
6.3.1整合Junit
步骤 1: 引入依赖
pom.xml
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>
步骤 2: 编写测试类
test\java 下创建一个 AccountServiceTest, 这个名字任意
package com.itheima.service;

import com.itheima.config.SpringConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//设置类运行器
@RunWith(SpringJUnit4ClassRunner.class)
//设置Spring环境对应的配置类
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
    //支持自动装配注入bean
    @Autowired
    private AccountService accountService;

    @Test
    public void testFindById(){
        System.out.println(accountService.findById(1));

    }

    @Test
    public void testFindAll(){
        System.out.println(accountService.findAll());
    }


}
注意 :
单元测试,如果测试的是注解配置类,则使用 @ContextConfiguration(classes = 配置
.class)
单元测试,如果测试的是配置文件,则使用 @ContextConfiguration(locations={ 配置文件
,...})
Junit 运行后是基于 Spring 环境运行的,所以 Spring 提供了一个专用的类运行器,这个务必要设
置,这个类运行器就在 Spring 的测试专用包中提供的,导入的坐标就是这个东西
SpringJUnit4ClassRunner
上面两个配置都是固定格式,当需要测试哪个 bean 时,使用自动装配加载对应的对象,下面的工
作就和以前做 Junit 单元测试完全一样了
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值