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");
相关推荐
怡人蝶梦几秒前
Java后端技术栈问题排查实战:Spring Boot启动慢、Redis缓存击穿与Kafka消费堆积
java·jvm·redis·kafka·springboot·prometheus
瓯雅爱分享5 分钟前
MES管理系统:Java+Vue,含源码与文档,实现生产过程实时监控、调度与优化,提升制造企业效能
java·mysql·vue·软件工程·源代码管理
蓝色天空的银码星6 分钟前
Springcloud Alibaba自定义负载均衡详解
spring·spring cloud·负载均衡
鬼多不菜1 小时前
一篇学习CSS的笔记
java·前端·css
深色風信子1 小时前
Eclipse 插件开发 5.3 编辑器 监听输入
java·eclipse·编辑器·编辑器 监听输入·插件 监听输入
yezipi耶不耶1 小时前
Rust入门之并发编程基础(一)
开发语言·后端·rust
bobz9651 小时前
cirros 慢的原因 checking http://169.254.169.254
后端
Blossom.1181 小时前
人工智能在智能健康监测中的创新应用与未来趋势
java·人工智能·深度学习·机器学习·语音识别
shangjg31 小时前
Kafka 如何保证不重复消费
java·分布式·后端·kafka