Spring框架核心IOC的使用:IOC的作用+Bean管理+实例化Bean的方式+DI依赖注入

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");
相关推荐
azhou的代码园1 分钟前
基于JAVA+SpringBoot+Vue的制造装备物联及生产管理ERP系统
java·spring boot·制造
wm104342 分钟前
java web springboot
java·spring boot·后端
smile-yan43 分钟前
Provides transitive vulnerable dependency maven 提示依赖存在漏洞问题的解决方法
java·maven
老马啸西风44 分钟前
NLP 中文拼写检测纠正论文-01-介绍了SIGHAN 2015 包括任务描述,数据准备, 绩效指标和评估结果
java
Earnest~1 小时前
Maven极简安装&配置-241223
java·maven
皮蛋很白1 小时前
Maven 环境变量 MAVEN_HOME 和 M2_HOME 区别以及 IDEA 修改 Maven repository 路径全局
java·maven·intellij-idea
青年有志1 小时前
JavaWeb(一) | 基本概念(web服务器、Tomcat、HTTP、Maven)、Servlet 简介
java·web
上海研博数据1 小时前
flink+kafka实现流数据处理学习
java
KpLn_HJL1 小时前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode
小扳2 小时前
微服务篇-深入了解 MinIO 文件服务器(你还在使用阿里云 0SS 对象存储图片服务?教你使用 MinIO 文件服务器:实现从部署到具体使用)
java·服务器·分布式·微服务·云原生·架构