Spring框架核心IOC的使用:IOC的作用+Bean管理+实例化Bean的方式+DI依赖注入
- 
- 一、项目环境搭建
 - 
- [1.1 新建maven项目](#1.1 新建maven项目)
 - [1.2 配置maven](#1.2 配置maven)
 - [1.3 配置applicationContext.xml](#1.3 配置applicationContext.xml)
 
 - 二、认识IOC
 - 三、bean管理
 - 
- [3.1 bean中属性的介绍](#3.1 bean中属性的介绍)
 - [3.2 具体示例](#3.2 具体示例)
 - 
- [3.2.1 bean对象的生命周期](#3.2.1 bean对象的生命周期)
 - [3.2.2 init-method与destroy-method](#3.2.2 init-method与destroy-method)
 
 
 - 四、实例化bean的三种方式
 - 
- [4.1 无参的构造方法](#4.1 无参的构造方法)
 - [4.2 静态工厂实例化方式](#4.2 静态工厂实例化方式)
 - [4.3 实例化工厂实例化方式](#4.3 实例化工厂实例化方式)
 
 - 五、DI依赖注入
 - 
- [5.1 认识DI](#5.1 认识DI)
 - [5.2 依赖注入的方式](#5.2 依赖注入的方式)
 - 
- [5.2.1 属性的set方法注入值的方式](#5.2.1 属性的set方法注入值的方式)
 - [5.2.2 构造方法注入值的方式](#5.2.2 构造方法注入值的方式)
 
 
 - 六、对其他数据类型的注入
 - 
- [6.1 对数组的注入](#6.1 对数组的注入)
 - [6.2 对可变数组的注入](#6.2 对可变数组的注入)
 - [6.3 对map的注入](#6.3 对map的注入)
 - [6.4 对Properties注入](#6.4 对Properties注入)
 - [6.5 对自定义类型的注入](#6.5 对自定义类型的注入)
 
 - 七、多配置文件的加载方式
 
 
Spring框架合集:
Spring框架核心IOC的使用:IOC的作用+Bean管理+实例化Bean的方式+DI依赖注入
Spring框架核心IOC的使用:配置式开发+注解式开发+纯注解式开发
Spring框架整合junit:包含配置文件的方式以及纯注解开发的方式
maven下载配置可以参考:maven配置
一、项目环境搭建
1.1 新建maven项目
点击新建项目,选择创建一个maven项目


1.2 配置maven

改成本地maven的路径

在pom文件中创建dependencies,在里面可以添加坐标依赖

打开Maven Repository: Search/Browse/Explore (mvnrepository.com)
搜索需要的jar包,添加坐标依赖之后,maven会帮助导入项目需要的资源



在pom文件中添加坐标依赖
            
            
              xml
              
              
            
          
          <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
        1.3 配置applicationContext.xml
目录层级

在resources创建配置文件applicationContext.xml
            
            
              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>
        
二、认识IOC
IOC控制反转:将对象的创建反转给spring框架,主要作用就是降低了程序的耦合度
下面通过一个例子,传统方式创建对象和使用IOC的方式创建对象,来简单体会一下IOC
首先在service下创建好需要的类

UserService接口
            
            
              java
              
              
            
          
          public interface UserService {
    public void hello();
}
        UserServiceImpl类
            
            
              java
              
              
            
          
          public class UserServiceImpl implements UserService {
    @Override
    public void hello() {
        System.out.println("hello");
    }
}
        接着在test下的java目录下创建UserServiceTest类进行测试

加入@Test注解是为了让方法运行
其中的run方法是传统创建对象,run1是用springIOC的方式创建对象
            
            
              java
              
              
            
          
          public class UserServiceTest {
    //传统创建对象方法
    @Test
    public void run(){
        UserService userService = new UserServiceImpl();
        userService.hello();
    }
    //用springIOC的方式创建对象,ioc是一个map key是对象的标识,value是ioc创建的对象
    @Test
    public void run1(){
        //创建spring ioc工厂,加载spring的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //FileSystemXmlApplicationContext另一种,配置文件在磁盘
        //获取bean对象,返回的是Object对象,强转
        UserService userService = (UserService) ac.getBean("xx");
        //调用方法
        userService.hello();
    }
}
        使用用springIOC的方式创建对象,还要配置applicationContext.xml文件,在beans中加入,创建好ioc工厂之后可以通过id拿到需要的class,通过程序创建类底层是反射
            
            
              xml
              
              
            
          
          <!--    id:创建类的标识 class:需要创建哪个类-->
    <bean id="xx" class="com.service.impl.UserServiceImpl"></bean>
        ApplicationContext接口,这个工厂接口,使用该接口可以获取具体的bean对象,该接口下有两个具体的实现类
- ClassPathXmlApplicationContext,加载类路径下的spring配置文件(常用)
 - FileSystemXmlApplicationContext,加载本地磁盘下的spring配置文件,项目与配置文件分离管理(不常用)
 
三、bean管理
3.1 bean中属性的介绍
- id属性:bean起个名字,唯一性,取值要求:必须以字母开始,可以使用字母、数字、连字符、下划线,不能出现特殊字符
 - class属性:bean对象的全路径
 - scope属性:表示bean对象的作用范围
- singleton:单例(默认)最常用的方式,生命周期跟配置文件一样,加载配置文件,实例创建
 - prototype:多例,不是加载配置文件的时候创建实例的,而是获取实例时才创建实例
 - request:多例,不常用,应用在web项目中,每次http请求的时候会创建一个新的实例
 - session:多例,不常用,应用在web项目中,同一个http session共享一个实例
 
 - init-method:bean对象创建时可以配置一个指定方法并自动调用
 - destroy-method:bean对象销毁时可以配置一个指定方法并自动调用
 
3.2 具体示例
3.2.1 bean对象的生命周期
在UserServiceImpl类中生成构造方法
            
            
              java
              
              
            
          
              public UserServiceImpl() {
        System.out.println("我创建了");
    }
        修改applicationContext.xml文件,scope改为singleton
            
            
              xml
              
              
            
          
              <bean id="xx" class="com.service.impl.UserServiceImpl" scope="singleton"></bean>
        修改测试类UserServiceTest中的run1方法,只是加载配置文件,然后运行
            
            
              java
              
              
            
          
              @Test
    public void run1(){
        //创建spring ioc工厂,加载spring的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //FileSystemXmlApplicationContext另一种,配置文件在磁盘
        //获取bean对象,返回的是Object对象,强转
        //UserService userService = (UserService) ac.getBean("xx");
        //调用方法
        //userService.hello();
    }
        运行结果

然后修改applicationContext.xml,然后运行
            
            
              xml
              
              
            
          
              <bean id="xx" class="com.service.impl.UserServiceImpl" scope="prototype"></bean>
        运行结果

此时并未输出"我创建了",修改测试类,然后再运行
            
            
              java
              
              
            
          
              @Test
    public void run1(){
        //创建spring ioc工厂,加载spring的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //FileSystemXmlApplicationContext另一种,配置文件在磁盘
        //获取bean对象,返回的是Object对象,强转
        UserService userService = (UserService) ac.getBean("xx");
        //调用方法
        userService.hello();
    }
        运行结果

从这个例子中可以体会到singleton与prototype生命周期的不同
3.2.2 init-method与destroy-method
修改UserServiceImpl类
            
            
              java
              
              
            
          
              public void init(){
        System.out.println("init");
    }
        修改applicationContext.xml
            
            
              xml
              
              
            
          
              <bean id="xx" class="com.service.impl.UserServiceImpl" init-method="init"></bean>
        运行测试类中的run1方法,会发现自动调用了init方法,destroy-method同理

四、实例化bean的三种方式
4.1 无参的构造方法
默认是无参的构造方法(默认方式,基本上都是使用这种)
            
            
              xml
              
              
            
          
          <bean id="xx" class="com.service.impl.UserServiceImpl" init-method="init" ></bean>
        注意:如果构造方法有参数,此时一定要保留无参的构造方法,不然程序会报错
ioc反射底层默认调用的是无参的构造方法
4.2 静态工厂实例化方式
静态工厂实例化方式,好处是可以自己编写业务逻辑
首先创建com.util包,然后创建一个StaticFactory类,在类中我们可以编写业务逻辑,只需要最后返回一个User类
            
            
              java
              
              
            
          
          public class StaticFactory {
    public static UserService createUs(){
        System.out.println("通过静态工厂的方式");
        //编写很多业务逻辑 ... ...
        return new UserServiceImpl();
    }
}
        配置applicationContext.xml文件,这里的类是编写业务逻辑的类,方法调用的是createUs,返回需要的类
            
            
              xml
              
              
            
          
              <bean id="xx" class="com.util.StaticFactory" factory-method="createUs"></bean>
        在测试类中运行run1方法

4.3 实例化工厂实例化方式
实例化工厂实例化方式,好处是可以自己编写业务逻辑
在com.util包下创建一个DFactory类
            
            
              java
              
              
            
          
          public class DFactory {
    public  UserService createUs(){
        System.out.println("通过实例化工厂的方式");
        //编写很多业务逻辑 ... ...
        return new UserServiceImpl();
    }
}
        配置applicationContext.xml文件,先把DFactory交给bean管理,方法调用的是createUs,返回需要的类
            
            
              xml
              
              
            
          
          <bean id="DFactory" class="com.util.DFactory" ></bean>
<bean id="xx" factory-bean="DFactory" factory-method="createUs"></bean>
        运行测试类
            
            
              java
              
              
            
          
          @Test
public void run1(){
    //创建spring ioc工厂,加载spring的配置文件
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    //FileSystemXmlApplicationContext另一种,配置文件在磁盘
    //获取bean对象,返回的是Object对象,强转
    UserService userService = (UserService) ac.getBean("xx");
    //调用方法
    userService.hello();
}
        
五、DI依赖注入
Dependency Injection 依赖注入在spring框架负责创建bean对象时,动态的将依赖对象注入到其他bean对象中
可以理解为赋值
5.1 认识DI
在dao层中创建一个接口UserDao,再创建一个实现类UserDaoImpl
            
            
              java
              
              
            
          
          public interface UserDao {
    public void hello();
}
        
            
            
              java
              
              
            
          
          public class UserDaoImpl implements UserDao {
    @Override
    public void hello() {
        System.out.println("持久层你好");
    }
}
        然后在service层创建UserService接口,再创建一个实现类UserServiceImpl
            
            
              java
              
              
            
          
          public interface UserService {
    public void hello();
}
        
            
            
              java
              
              
            
          
          public class UserServiceImpl implements UserService {
    private UserDao userDao;
    @Override
    public void hello() {
        System.out.println("业务层你好");
        userDao.hello();
    }
}
        目录结构

此时我们想通过业务层来调用dao层中的方法,在UserServiceImpl创建了一个UserDao的对象,但是如果此时运行的话,会报空指针的错误。因此我们修改一下UserServiceImpl类,里面new一个UserDaoImpl
            
            
              java
              
              
            
          
          public class UserServiceImpl implements UserService {
	private UserDao userDao = new UserDaoImpl();
    @Override
    public void hello() {
        System.out.println("业务层你好");
        userDao.hello();
    }
}
        修改之后运行结果

这种赋值的方式就是依赖注入,就是给变量赋值。通过这种方式,业务层可以调用持久层的方法
5.2 依赖注入的方式
5.2.1 属性的set方法注入值的方式
修改UserServiceImpl类,注意这种方式必须有set方法
            
            
              java
              
              
            
          
          public class UserServiceImpl implements UserService {
    private UserDao userDao;
    private String name;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "UserServiceImpl{" +
                "userDao=" + userDao +
                ", name='" + name + '\'' +
                '}';
    }
    @Override
    public void hello() {
        System.out.println("业务层你好");
        userDao.hello();
    }
}
        修改配置文件applicationContext.xml,此时为name和userDao赋值
            
            
              xml
              
              
            
          
              <bean id="userDaoImpl" class="com.dao.impl.UserDaoImpl"></bean>
    <bean id="xx" class="com.service.impl.UserServiceImpl">
        <property name="name" value="lm"></property>
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>
        其中的property标签是为类中的变量赋值
- 简单类型(基本类型+字符串)property标签使用value属性赋值
 - 自定义应用类 property标签使用ref属性赋值
 
先把UserDaoImpl交给IOC工厂管理,等到用时使用ref赋值
在UserServiceTest类中运行run1方法
            
            
              java
              
              
            
          
          @Test
    public void run1(){
        //创建spring ioc工厂,加载spring的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //FileSystemXmlApplicationContext另一种,配置文件在磁盘
        //获取bean对象,返回的是Object对象,强转
        UserService userService = (UserService) ac.getBean("xx");
        //调用方法
        System.out.println(userService);
    }
        
5.2.2 构造方法注入值的方式
修改UserServiceImpl类,注意使用这种方式时要保留类的无参构造方法,因为实例化bean默认调用的是无参的构造方法,如果不保留的话程序报错
            
            
              java
              
              
            
          
          public class UserServiceImpl implements UserService {
    private UserDao userDao;
    private String name;
    public UserServiceImpl() {
    }
    public UserServiceImpl(UserDao userDao, String name) {
        this.userDao = userDao;
        this.name = name;
    }
    @Override
    public String toString() {
        return "UserServiceImpl{" +
                "userDao=" + userDao +
                ", name='" + name + '\'' +
                '}';
    }
}
        修改applicationContext.xml,这里使用的是constructor-arg标签,注意构造方法的赋值要与配置文件中保持一致不能多也不能少,这里的配置文件中是有name和userDao,如果只有name那么构造方法也应该只有name一个参数
            
            
              xml
              
              
            
          
          <bean id="userDaoImpl" class="com.dao.impl.UserDaoImpl"></bean>
<bean id="xx" class="com.service.impl.UserServiceImpl">
    <constructor-arg name="name" value="Jack"></constructor-arg>
    <constructor-arg name="userDao" ref="userDaoImpl"></constructor-arg>
</bean>
        运行run1方法

六、对其他数据类型的注入
这里使用都是set方法注入值的方式
6.1 对数组的注入
创建CollectionBean类
            
            
              java
              
              
            
          
          public class CollectionBean {
    private String[] arr;
    public void setArr(String[] arr) {
        this.arr = arr;
    }
    @Override
    public String toString() {
        return "CollectionBean{" +
                "arr=" + Arrays.toString(arr) +
                '}';
    }
}
        配置applicationContext.xml文件,为arr赋值
            
            
              xml
              
              
            
          
          <bean id="cb" class="com.service.CollectionBean">
    <property name="arr">
        <array>
            <value>李明</value>
            <value>xiaomi</value>
        </array>
    </property>
</bean>
        在测试类中创建方法,查看结果
            
            
              java
              
              
            
          
          @Test
public void run2(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    CollectionBean cB = (CollectionBean) ac.getBean("cb");
    System.out.println(cB);
}
        
6.2 对可变数组的注入
修改CollectionBean类
            
            
              java
              
              
            
          
          public class CollectionBean {
    private List<String> list;
    public void setList(List<String> list) {
        this.list = list;
    }
    @Override
    public String toString() {
        return "CollectionBean{" +
                "list=" + list +
                '}';
    }
}
        修改配置文件
            
            
              xml
              
              
            
          
          <bean id="cb" class="com.service.CollectionBean">
    <property name="list">
        <list>
            <value>李明</value>
            <value>xiaomi</value>
        </list>
    </property>
</bean>
        6.3 对map的注入
修改CollectionBean类
            
            
              java
              
              
            
          
          public class CollectionBean {
    private Map<String,String> map;
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
    @Override
    public String toString() {
        return "CollectionBean{" +
                "map=" + map +
                '}';
    }
}
        修改配置文件
            
            
              xml
              
              
            
          
              <bean id="cb" class="com.service.CollectionBean">
        <property name="map">
            <map>
                <entry key="xiaomi" value="SU7"></entry>
                <entry key="byd" value="海豹"></entry>
            </map>
        </property>
    </bean>
        6.4 对Properties注入
修改CollectionBean类
            
            
              java
              
              
            
          
          public class CollectionBean {
    private Properties properties;
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    @Override
    public String toString() {
        return "CollectionBean{" +
                "properties=" + properties +
                '}';
    }
}
        修改配置文件
            
            
              xml
              
              
            
          
              <bean id="cb" class="com.service.CollectionBean">
        <property name="properties">
            <props>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
    </bean>
        6.5 对自定义类型的注入
修改CollectionBean类
            
            
              java
              
              
            
          
          public class CollectionBean {
    private UserService[] userServices;
    public void setUserServices(UserService[] userServices) {
        this.userServices = userServices;
    }
    @Override
    public String toString() {
        return "CollectionBean{" +
                "userServices=" + Arrays.toString(userServices) +
                '}';
    }
}
        修改配置文件
            
            
              xml
              
              
            
          
              <bean id="userS" class="com.service.impl.UserServiceImpl"></bean>
    <bean id="cb" class="com.service.CollectionBean">
        <property name="userServices">
            <ref bean="userS"></ref>
        </property>
    </bean>
        七、多配置文件的加载方式
如果有多个配置文件,如何使用多配置文件开发

1、在主配置文件中使用< import >标签
            
            
              xml
              
              
            
          
          <import resource="applicationContext2.xml"></import>
        2、创建工厂时直接加载多个配置文件
            
            
              java
              
              
            
          
          ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext.xml");