(一)初见Spring、IOC控制反转介绍及xml配置注解配置、小实战(图文教学,超级详细)

实战项目完成代码:SpringTest——GitHub


1.简介

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

1.1 spring 的体系结构

在这里插入图片描述

2.IOC(Inverse Of Control:反转控制)

2.1 过去存在的问题

程序间的耦合性过高。耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合

以前当我们需要一个对象的时候,我们需要使用new关键字来创建对象

Student student = new Student();

但是当我们没有Student这个类时,在编译阶段就会进行报错。这种编译期依赖关系,应该在我们开发中杜绝。我们需要优化代码解决。
不知道你有没有想到什么方法?我们以前肯定在哪里解决过这种问题。

在使用JDBC操作,注册驱动时

Class.forName("com.mysql.jdbc.Driver");

Class.forName 使用了反射的机制

2.2 Spring的解决方案

工厂模式解耦
当启动服务器应用加载的时候,让一个类中的
方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。

什么是容器?什么的工厂?
容器就是用于存放创建出来的对象Map。
工厂就是负责给我们从容器中获取指定对象的类。

以前我们获取对象是自己主动的new一个对象
在这里插入图片描述
现在我们使用Spring后,我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。
在这里插入图片描述
我们将我们的控制权力交给工厂来控制,这种被动接收的方式获取对象的思想就是控制反转,它是 spring 框架的核心之一。

3.IOC 快速入门

3.1 准备工作

  1. 创建父工程springtest,并导入坐标,删除src文件夹
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
    </dependencies>
  1. 创建子工程day1_ioc

  2. 创建com.lois.dao.UserDao接口类和com.lois.dao.impl.UserDaoImpl实现类

public interface UserDao {
    String findAll();
}
public class UserDaoImpl implements UserDao {
    
    //仅是模拟dao
    public String findAll() {
        return "查询出所有用户";
    }
}
  1. 创建com.lois.service.UserService接口类和com.lois.service.impl.UserServiceImpl实现类
public interface UserService {
    String findAll();
}
public class UserServiceImpl implements UserService {

    //此处的耦合问题我们在后面解决
    private UserDao userDao = new UserDaoImpl();

    public String findAll() {
        return userDao.findAll();
    }
}

3.2 基于XML的配置

  1. 在resources文件夹中创建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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>
  1. 让Spring管理我们写的类,在配置文件中配置service和dao
    <!-- bean 标签:用于配置让 spring 创建对象,并且存入 ioc 容器之中
            id 属性:对象的唯一标识。
            class 属性:指定要创建对象的全限定类名-->
    <bean id="userDao" class="com.lois.dao.impl.UserDaoImpl" />
    <bean id="userService" class="com.lois.service.impl.UserServiceImpl"/>
  1. 编写com.lois.client.UserClient测试类(注意!此类在main.java包中)
/**
 * 测试类
 */
public class UserClient {
    public static void main(String[] args) {
        //根据配置文件生成Spring容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");

        //从IOC容器中根据id获取对象
        UserDao userDao = ac.getBean("userDao", UserDao.class);
        System.out.println(userDao);
        //注意getBean的重载
        UserService userService = (UserService) ac.getBean("userService");
        System.out.println(userService);
    }
}
  1. 执行测试
com.lois.service.impl.UserServiceImpl@3ffc5af1
com.lois.dao.impl.UserDaoImpl@5e5792a0

4. 基于XML的IOC细节

在这里插入图片描述
在这里插入图片描述

4.1 BeanFactory 和 ApplicationContext 的区别

BeanFactory 才是 Spring 容器中的顶层接口。
ApplicationContext 是它的子接口。
BeanFactory 和 ApplicationContext 的区别:

  • 创建对象的时间点不一样。
    • ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
    • BeanFactory:什么使用什么时候创建对象。

你可以修改com.lois.client.UserClient测试类

//        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        BeanFactory ac = new XmlBeanFactory(new ClassPathResource("ApplicationContext.xml"));

然后在service和dao类中加入默认构造函数

public UserServiceImpl(){
        System.out.println("构建了UserServiceImpl");
    }
	public UserDaoImpl(){
        System.out.println("构建了UserDaoImpl");
    }

使用断点调试,观察控制台输出

4.2 ApplicationContext 接口的实现类

  • ClassPathXmlApplicationContext:它是从类的根路径下加载配置文件 (推荐)
  • FileSystemXmlApplicationContext:它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
  • AnnotationConfigApplicationContext:当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

4.3 bean 标签和管理对象细节

4.3.1 bean标签

作用
用于配置对象让 spring 来创建的。
默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
属性
id:给对象在容器中提供一个唯一标识。用于获取对象。
class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
scope:指定对象的作用范围。

  • singleton :默认值,单例的.
  • prototype :多例的.
  • request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
  • session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
  • global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么globalSession 相当于 session.

init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。

4.3.2 bean 的作用范围和生命周期

单例对象:scope=“singleton”

一个应用只有一个对象的实例。它的作用范围就是整个引用。

生命周期:

  • 对象出生:当应用加载,创建容器时,对象就被创建了。
  • 对象活着:只要容器在,对象一直活着。
  • 对象死亡:当应用卸载,销毁容器时,对象就被销毁了。

多例对象:scope=“prototype”

每次访问对象时,都会重新创建对象实例。

生命周期:

  • 对象出生:当使用对象时,创建新的对象实例。
  • 对象活着:只要对象在使用中,就一直活着。
  • 对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。

注意:在使用单例对象的时候,创建IOC容器时就创建了单例对象,但是多例对象时是在第一次使用对象的时候创建,有点类似Mybatis中的延迟加载。Spring真的很智能!

4.3.3 实例化 Bean 的三种方式

第一种方式:使用默认无参构造函数(我们上面已经试过了,就不多说了)
第二种方式:spring 管理静态工厂——使用静态工厂的方法创建对象

  1. 创建静态工厂类com.lois.factory.StaticFactory
 public class StaticFactory {
    public static UserDaoImpl createUserDaoImpl(){
        return new UserDaoImpl();
    }
}
  1. 修改ApplicationContext.xml配置文件
<!--<bean id="userDao" class="com.lois.dao.impl.UserDaoImpl" />-->
<!-- 此种方式是:
使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
id 属性:指定 bean 的 id,用于从容器中获取
class 属性:指定静态工厂的全限定类名
factory-method 属性:指定生产对象的静态方法-->
<bean id="userDao"  class="com.lois.factory.StaticFactory" factory-method="createUserDaoImpl"/>

第三种方式:spring 管理实例工厂——使用实例工厂的方法创建对象

  1. 创建实例工厂类com.lois.factory.InstanceFactory
public class InstanceFactory {
    public UserServiceImpl createUserServiceImpl(){
        return new UserServiceImpl();
    }
}
  1. 修改ApplicationContext.xml配置文件
<!--<bean id="userService" class="com.lois.service.impl.UserServiceImpl"/>-->
<!-- 此种方式是:
    先把工厂的创建交给 spring 来管理。
    然后在使用工厂的 bean 来调用里面的方法
    factory-bean 属性:用于指定实例工厂 bean 的 id。
    factory-method 属性:用于指定实例工厂中创建对象的方法。-->
<bean id="instanceFactory" class="com.lois.factory.InstanceFactory"/>
<bean id="userService" factory-bean="instanceFactory" factory-method="createUserServiceImpl"/>

4.4 spring 的依赖注入

4.4.1 什么的依赖注入

以前我们的程序中需要一个对象使用new来实现,但是现在我们将对象都交给了Spring管理,但是程序不可能不使用其他对象(也就是说耦合性不可能消失,只能降低)。我们使用Spring将IOC容器中的对象赋值给程序中需要用的地方,这就是依赖注入。

4.4.2 构造函数注入

优势:在获取bean对象时, 注入数据是必须的
弊端:如果有一些数据用不到,也必须提供

  1. 修改UserService接口类和UserServiceImpl实现类
public interface UserService {
    String findAll();
    void show();
}
public class UserServiceImpl implements UserService {

    private UserDao userDao;
    private String username;
    private int age;

    public UserServiceImpl(UserDao userDao,String username,int age){
        this.userDao = userDao;
        this.username = username;
        this.age = age;
    }

    public UserServiceImpl(){
        System.out.println("构建了UserServiceImpl");
    }

    public void show(){
        System.out.println(username+","+age+","+userDao);
    }

    public String findAll() {
        return userDao.findAll();
    }
}
  1. 修改ApplicationContext.xml配置文件,将以前的userService的bean注释
<!-- 使用构造函数的方式,给 service 中的属性传值
    要求:
        类中需要提供一个对应参数列表的构造函数。
    涉及的标签:
        constructor-arg
    属性:
        index:指定参数在构造函数参数列表的索引位置
        type:指定参数在构造函数中的数据类型
        name:指定参数在构造函数中的名称 (常用)
    =======上面三个都是找给谁赋值,下面两个指的是赋什么值的==============
        value:它能赋的值是基本数据类型和 String 类型
        ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean-->
    <bean id="userService" class="com.lois.service.impl.UserServiceImpl">
        <constructor-arg index="0" ref="userDao"/>
        <constructor-arg type="java.lang.String" value="张三"/>
        <!-- Spring会将18转换成int类型,智能!-->
        <constructor-arg name="age" value="18"/>
    </bean>
  1. 在com.lois.client.UserClient的后面添加代码,执行测试
userService.show();
张三,18,com.lois.dao.impl.UserDaoImpl@6b09bb57
4.4.3 set方法注入

优势:创建对象时没有限时,不用数据时也可以调用无参构造函数
弊端:不能确保创建的对象中数据有值

  1. 修改UserServiceImpl类,注释刚刚写的构造函数,生成set方法
  2. 修改ApplicationContext.xml配置文件,并将构造函数注入的注释
<!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式
    涉及的标签:
        property
    属性:
        name:找的是类中 set 方法后面的部分
        ref:给属性赋值是其他 bean 类型的
        value:给属性赋值是基本数据类型和 string 类型的
        实际开发中,此种方式用的较多。-->
<bean id="userService" class="com.lois.service.impl.UserServiceImpl">
    <property name="username" value="李四"/>
    <property name="age" value="18"/>
    <property name="userDao" ref="userDao"/>
</bean>
  1. 运行测试类
李四,18,com.lois.dao.impl.UserDaoImpl@20398b7c
4.4.4 注入集合属性

当变量类型是集合时,我们该如何做?

  1. 修改UserDao接口类和UserDaoImpl实体类,生产set方法
public interface UserDao {
    String findAll();
    void show();
}
public class UserDaoImpl implements UserDao {
    private String[] strs;
    private List<String> list;
    private Set<String> set;
    private Map<String,String> map;
    private Properties props;
    
	public void show() {
        System.out.println(Arrays.toString(strs));
        System.out.println(list);
        System.out.println(set);
        System.out.println(map);
        System.out.println(props);
    }
  1. 修改ApplicationContext.xml配置文件,将上次的userDao的bean标签注释起来
    <!-- 注入集合数据(只要结构相同,标签可以互换)
            List 结构的:
            array,list,set
            Map 结构的
            map,entry,props,prop -->
    <bean id="userDao"  class="com.lois.factory.StaticFactory" factory-method="createUserDaoImpl">
        <property name="strs">
            <array>
                <value>aaa</value>
                <value>bbb</value>
                <value>ccc</value>
            </array>
        </property>
        <property name="list">
            <set>
                <value>aaa</value>
                <value>bbb</value>
                <value>ccc</value>
            </set>
        </property>
        <property name="set">
            <list>
                <value>aaa</value>
                <value>bbb</value>
                <value>ccc</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="username" value="aaa"/>
                <entry key="password" value="123"/>
            </map>
        </property>
        <property name="props">
            <props>
                <prop key="username">aaa</prop>
                <prop key="password">123</prop>
            </props>
        </property>
    </bean>
  1. 修改测试类,执行测试
userDao.show();

控制台输出

[aaa, bbb, ccc]
[aaa, bbb, ccc]
[aaa, bbb, ccc]
{username=aaa, password=123}
{password=123, username=aaa}

5.基于注解的 IOC 配置

5.1 环境搭建

  1. 创建子模块day1_annotation_ioc,将day1_ioc工程下的main文件夹复制过来(不要在idea中进行)
  2. 修改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>

5.2 常用注解

5.2.1 用于创建对象

使用xml的时候我们用的是<bean id="" class="">

注解中使用:
@Component(一般不属于下面三个领域时使用)

衍生出来三个注解,作用及属性都是一模一样的,只不过是提供了更加明确的语义化

@Controller:一般用于表现层的注解。
@Service:一般用于业务层的注解。
@Repository:一般用于持久层的注解。

作用:
	把资源让 spring 来管理。相当于在 xml 中配置一个 bean。
属性:
	value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。
5.2.2 数据注入

相当于:<property name="" ref="">
<property name="" value="">

注解中使用:
@Autowired

作用:
	自动按照类型注入。当使用注解注入属性时,set 方法可以省略。它只能注入其他 bean 类型。
	当有多个类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就报错。

@Qualifier

作用:
	在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和
	@Autowire 一起使用;但是给方法参数注入时,可以独立使用。
属性:
	value:指定 bean 的 id。

@Resource

作用:
	直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。
属性:
	name:指定 bean 的 id。

@Value

作用:
	注入基本数据类型和 String 类型数据的
属性:
	value:用于指定值

集合类型的注入只能通过xml来实现

5.2.2 用于改变作用范围的

相当于:<bean id="" class="" scope="">

注解中使用:
@Scope

作用:
	指定 bean 的作用范围。
属性:
	value:指定范围的值。
	取值:singleton(默认,单例,常用) prototype(多例,常用) request session globalsession
5.2.3 生命周期(了解)

相当于:<bean id="" class="" init-method="" destroy-method="" />
注解中使用
@PostConstruct

作用:
	用于指定初始化方法。

@PreDestroy

作用:
	用于指定销毁方法。
5.2.4 纯注解开发

如果我们不想使用xml配置文件怎么办,Spring给我们提供了几个新注解
@Configuration

作用:
	用于指定当前类是一个 spring 配置类(用于替换ApplicationContext.xml),当创建容器时会从该类上加载注解。
	获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class)。
属性:
	value:用于指定配置类的字节码
示例:
	@Configuration
	public class SpringConfiguration {
	}

@ComponentScan

作用:
	用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:<context:component-scan base-package="com.itheima"/>是一样的。
属性:
	basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。
示例
	@Configuration
	@ComponentScan("com.lois")
	public class SpringConfiguration {
	}

@Bean

作用:
	该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
属性:
	name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
细节:
	当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。查找的方式和Autowired注解的作用是一样的
示例
	public class JdbcConfig {
	@Bean(name="dataSource")
	public DataSource createDataSource() {
	}

@PropertySource

作用:
	用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性:
	value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:

@Import

作用:
	用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。
属性:
	value[]:用于指定其他配置类的字节码。

5.3 快速入门

  1. Spring如何知道我们使用的是注解还是xml配置呢?使用context:component-scan标签,添加扫描的包,修改ApplicationContext.xml配置文件
<context:component-scan base-package="com.lois"/>
  1. 修改UserDaoImpl类
@Repository
public class UserDaoImpl implements UserDao {
    public void show() {
    }

    public UserDaoImpl(){
        System.out.println("构建了UserDaoImpl");
    }
    //仅是模拟dao
    public String findAll() {
        return "查询出所有用户";
    }
}
  1. 修改UserServiceImpl类
@Service
@Scope("singleton")//单例
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDaoImpl;
    @Value("小章")
    private String username;
    @Value("18")
    private int age;

    @PostConstruct
    public void init(){
        System.out.println("UserServiceImpl初始化");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("UserServiceImpl销毁了");
    }


    public UserServiceImpl(){
        System.out.println("构建了UserServiceImpl");
    }

    public void show(){
        System.out.println(username+","+age+","+userDaoImpl);
    }

    public String findAll() {
        return userDaoImpl.findAll();
    }
}
  1. 修改测试类UserClient
public class UserClient {
    public static void main(String[] args) {
        //根据配置文件生成Spring容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
//        BeanFactory ac = new XmlBeanFactory(new ClassPathResource("ApplicationContext.xml"));

        //从IOC容器中根据id获取对象
        UserDao userDao = ac.getBean("userDaoImpl", UserDao.class);
        System.out.println(userDao);
        //注意getBean的重载
        UserService userService = (UserService) ac.getBean("userServiceImpl");
        System.out.println(userService);

        userService.show();
        userDao.show();
        ac.close();
    }
}
  1. 执行测试
构建了UserDaoImpl
构建了UserServiceImpl
UserServiceImpl初始化
八月 16, 2019 5:00:25 下午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@4ccabbaa: startup date [Fri Aug 16 17:00:24 CST 2019]; root of context hierarchy
com.lois.dao.impl.UserDaoImpl@1dd02175
com.lois.service.impl.UserServiceImpl@31206beb
小章,18,com.lois.dao.impl.UserDaoImpl@1dd02175
UserServiceImpl销毁了

6. 小实战

学习了上面的内容,我们来写一个小实战练习一下,真正的从数据库中查一些数据。

6.1 注解+xml混用方式

  1. 使用sql脚本创建我们需要的数据(我们使用我写的Mybatis博客中的数据,如果你学过,可以跳过)
create database mybatistest;
use mybatistest;
drop table if exists `user`;
create table `user`(
	`id` int(10) primary key auto_increment,
	`name` varchar(20),
	`age` int(3)
);
insert into `user`(`name`,`age`) values('小明',22);
insert into `user`(`name`,`age`) values('小红',25);
  1. 创建子工程day1_ioc_example,在子包中导入坐标
<dependencies>
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>

        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
  1. 编写com.lois.dao.UserDao接口类和com.lois.dao.impl.UserDaoImpl实现类
public interface UserDao {
    public List<User> findAll();
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @Autowired
    private QueryRunner runner;

    public List<User> findAll() {
        try{
            return runner.query("select * from user",new BeanListHandler<User>(User.class));
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
  1. 编写com.lois.service.UserService接口类和com.lois.service.impl.UserServiceImpl实现类
public interface UserService {
    public List<User> findAll();
}
@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    public List<User> findAll() {
        return userDao.findAll();
    }
}
  1. 编写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">

    <!-- 告知spring在创建容器时要扫描的包 -->
    <context:component-scan base-package="com.lois"></context:component-scan>
    <!--配置QueryRunner-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源-->
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/mybatistest?serverTimezone=UTC&amp;characterEncoding=utf-8&amp;useSSL=false"></property>
        <property name="user" value="root"></property>
        <property name="password" value="123123123"></property>
    </bean>
</beans>
  1. 编写测试类com.lois.test.UserTest
public class UserTest {
    @Test
    public void findAllUser(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        UserService userService = ac.getBean("userService", UserService.class);
        System.out.println(userService.findAll());
    }
}
  1. 执行测试方法
[User{id=1, name='小明', age=22}, User{id=2, name='小红', age=25}]

6.2 纯注解方式

  1. 创建子工程day1_ioc_example_withoutxml,在子包中导入坐标跟day1_ioc_example一样
  2. 将day1_ioc_example包中的main和test文件夹拷贝过来(不要在idea中拷贝)
  3. 创建配置类com.lois.config.SpringConfiguration
@Configuration
@ComponentScan("com.lois")
@PropertySource("classpath:druid.properties")
public class SpringConfiguration {

    //从properties中获取信息
    @Value("${driver}")
    private String driver;

    @Value("${url}")
    private String url;

    @Value("${username}")
    private String username;

    @Value("${password}")
    private String password;

    @Bean(name="runner")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }

    @Bean(name="dataSource")
    public DataSource createDataSource(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}
  1. 创建数据库信息文件druid.properties(在resources文件夹中)
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatistest?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false
username=root
password=123123123
  1. 修改测试类
@Test
    public void findAllUser(){
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        UserService userService = ac.getBean("userService", UserService.class);
        System.out.println(userService.findAll());
    }

此时我们不想在测试类使用AnnotationConfigApplicationContext,我们想使用Ioc注入的方式获取到UserService,我们该怎么办?

  1. 在子包中要添加坐标
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
  1. 修改测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class UserTest {

    @Autowired
    private UserService userService;

    @Test
    public void findAllUser(){
        System.out.println(userService.findAll());
    }
}

7.作业

上面的实战我们用的是注解开发,你能使用xml开发吗?


下一章:Spring AOP简介xml注解配置、JdbcTemplate、Spring事务控制


相关内容:
初见Spring、IOC控制反转介绍及xml配置注解配置、小实战

Spring AOP简介xml注解配置、JdbcTemplate、Spring事务控制


作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!
作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!
作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值