详解SpringIOC容器相关知识

一、前言

IOC控制反转,不是一种技术,而是一种设计思想,就是将原本在程序中手动创建对象的控制权,交给Spring框架来管理。

区别:

  • 没有IOC的思路:若要使用某个对象,就必须自己负责去写对象的创建
  • IOC的思路:若要使用某个对象,只需要从Spring容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权交给了Spring框架。
  • 好莱坞法则:Don't call me, I 'll call you

举例说明:

做菜,做蒜薹炒猪肉

你有两种做法:

第一种,自己养猪,然后种蒜薹。等到猪长大了,你就可以杀猪,蒜薹成熟了,就收割。然后开始炒,做成了蒜薹炒猪肉。

第二种,从农贸市场获取猪和蒜薹,拿回来直接炒,做成了蒜薹炒猪肉。

此时的IOC就相当于这个农贸市场,我要做菜,我去农贸市场拿过来就可以了,而不需要自己去弄。为什么要Java对象放到容器里?因为我们要做到拿来即用,便于管理。那你能管理农贸市场吗?你不能,那谁来管农贸市场?Spring!这就是控制反转IOC,我们把控制权交给了Spring框架,他来帮我们管这个农贸市场,他来养猪,他来种菜。我们只需在要菜的时候,去市场买就好了。

再举一个例子

过年了,想要给家里打扫个卫生,你想请几个钟点工来打扫。也有两种做法。

第一种:自己主动找,找身边人看看谁认识钟点工,你自己打电话邀约,谈价格

第二种:直接找家政公司,直接提出需求即可。

第一种方式就是我们自己创建对象的方式,自己主动new几个钟点工。而第二种就是spring给我们提供的IOC方式,家政公司就是一个容器,能给我提供很多的服务,钟点工对象是spring帮我们创建的。

又过了几天,我又想给厨房的油烟机清理一下,也能直接打电话给家政公司,提出需求。

那上述例子中的农贸市场和家政公司哪里来啊?

我们可以自己构建,就像自己成立一个公司一样。具体在程序中表现为:

1.使用配置文件或者注解的方式定义一下我们自己容器里存放的东西。

或者去别人的公司里找。具体在程序中表现为:

2.一定有很多人创建了自己的公司,这些服务都可以集成在我们自己的容器里,为我们提供强大的功能,比如spring自带很多的template模板类。

二、IOC原理实战

首先在pom.xml文件中加入spring的相关jar包。

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
</dependencies>

我们定义我们的接口和实现类

// UserDao接口
public interface UserDao {
    void getUser();
}
// UserDao实现类1,mysql实现
public class UserDaoImpl implements UserDao {
    public void getUser() {
        System.out.println("mysql实现");
    }
}
// UserDao实现类2,oracle实现
public class UserDaoImpl implements UserDao {
    public void getUser() {
        System.out.println("oracle实现");
    }
}

然后我们的业务实现类,在不使用set注入的情况下,是这样的:

//业务接口
public interface UserService {
    void getUser();
}
//业务实现类
public class UserServiceImpl implements UserService {
    //传统的方法中,如果这边要改变,那就必须将这里的语句改变才可以
    private UserDao userDao = new UserDaoImpl();

    public void getUser() {
        userDao.getUser();
    }
}

对应的测试类:

public class MyTest {
    public static void main(String[] args) {
        //用户实际调用的是业务层,不需要接触dao层
        UserServiceImpl userService =new UserServiceImpl();
        userService.getUser();
    }
}

但是你会发现使用这种方法如果我在测试这里想用oracle实现,那就必须新增一个业务实现类或者修改我原本的业务实现类,违反了开闭原则。

所以我们的业务实现类要使用set方法动态注入我们的UserDao实现类。

public class UserServiceImpl implements UserService {
    private UserDao userDao;
    // 利用set进行动态实现值的注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void getUser() {
        userDao.getUser();
    }
}

如此一来只需要在测试类中通过set方法,传入对应的实现类对象,就可以实现调用不同的实现对象的getUser方法。

public class MyTest {
    public static void main(String[] args) {
        // 利用set注入的方法,我们可以不需要修改service中的代码,从而实现多个不同对象的getUser方法
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoImpl());
        userService.getUser();//mysql实现
        userService.setUserDao(new UserDaoOracleImpl());
        userService.getUser();//oracle实现
    }
}

这两种模式的区别可以发现。之前,控制UserDao实现类的控制权,在程序员手上,程序员写在UserServiceImpl里,写死了对应的是实现类,如果要修改的话,程序员就必须去修改对应的代码。而后面这种方法,控制UserDao实现类的控制权,就已经不在程序员手上了。现在程序是被动接收对象,然后动态set注入实现了可以随意使用不同的实现类的getUser方法。

这其实就是一种控制反转IOC的原型。这种思想从本质上解决了问题,程序员不用再去管理对象的创建了。系统的耦合性大大降低。可以更加专注的在业务的实现上。spring的底层全部都是基于这种思想去实现的。

三、IOC本质

像上图所示,IOC本质上就是把左边变成了右边。本来是业务层里程序员写来主动决定调用的下面的Mysql还是Oracle,但是现在通过IOC,可以把主动权交给用户,让用户想用Mysql用Mysql,想用Oracle就用Oracle。

DI(依赖注入)是实现IOC的一种方法,在没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码再程序中,对象的创建由程序自己控制(也就是程序员自己写),控制反转(IOC)后将对象的创建移交给第三方了,控制反转的这个反转说的就是获得依赖对象的方式反转了。

采用XML配置方式配置Bean的时候,Bean的定义信息和实现是分离的,而采用注解的方式的时候两者是合为一体的,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目睹。

控制反转是一种通过描述(XML或者注解)并通过第三方去生产或获得特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方式是依赖注入(Dependency Injection,DI)

四、spring helloworld

找到1.2.2实例化容器部分,发现了其配置文件格式:

首先创建我们的实体类Hello:

package com.hj.pojo;
public class Hello {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

然后根据文档中所述,在resources文件下创建beans.xml文件来使用spring创建对象。beans.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">

    <!--使用spring来创建对象,在spring中这些都称为bean
    bean = 对象 相当于 new Hello();
    正常是 类型 变量名 = new 类型();
          Hello hello = new Hello();
    利用bean来实现,id就是变量名,class就是我们对象的类型
    里面的property相当于给对象中的属性设置一个值。
    -->
    <bean id="hello" class="com.hj.pojo.Hello">
        <!--
        ref:引用spring容器中创建好的对象
        value:具体的值,基本数据类型
        -->
        <property name="str" value="Spring"/>
    </bean>

</beans>

再次查看官方文档,查询如何使用容器。

可以看到需要借助一个工厂来读取bean的定义并进行访问,然后创建对象。

import com.hj.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
	public static void main(String[] args) {
		//获取spring的上下文对象
		ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		//我们的对象现在都在spring中管理了,我们要使用,直接去取出来就可以了
		Hello hello = (Hello) context.getBean("hello");
		System.out.println(hello.toString());//Hello{str='Spring'}
		//思考?
		//Hello对象是谁创建的?是由Spring创建的
		//Hello对象的属性是怎么设置的?是由Spring容器设置的
		}
	}

这个Hello对象由spring创建并且由spring容器设置属性的过程就是控制反转。

五、小结

控制:谁来控制对象的创建,传统的应用程序的对象是由程序本身控制创建的,使用spring后,对象是由spring来创建的。

反转:程序本身不创建对象,而变成被动的接收对象

依赖注入:就是利用set方法来进行注入

IOC是一种编程思想,由主动的编程去变成被动的接收。

我们回头看Hello类里左边有个豆子的标志了,这说明这个类已经被Spring托管了。

所谓的IoC,一句话来概括:对象由spring来创建,管理和装配。

到此这篇关于详解SpringIOC和容器相关知识的文章就介绍到这了,更多相关SpringIOC和容器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • spring在IoC容器中装配Bean详解

    1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean实例放入bean缓存池: 应用程序使用bean. 1.2.基于xml的配置 (1)xml文件概述 xmlns------默认命名空间 xmlns:xsi-------标准命名空间,用于指定自定义命名空间的schema文件 xmlns:xxx="aaaaa"-------自定义命名空间,xx

  • 使用Java注解模拟spring ioc容器过程解析

    使用注解,简单模拟spring ioc容器.通过注解给对象属性注入值. 项目结构 annotation 包,用于存放自定义注解 Component 注解表示该类为组件类,并需要声明名字 package priv.haidnor.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;

  • Spring核心容器IOC原理实例解析

    这篇文章主要介绍了Spring核心容器IOC原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 .BeanFactory Spring Bean 的创建是典型的工厂模式,这一系列的 Bean 工厂,也即 IOC 容器为开发者管理对象 间的依赖关系提供了很多便利和基础服务.最基本的 IOC 容器接口 BeanFactory,来看一下它的源码: public interface BeanFactory { //对 FactoryBean

  • Spring常用注解 使用注解来构造IoC容器的方法

    使用注解来构造IoC容器 用注解来向Spring容器注册Bean.需要在applicationContext.xml中注册<context:component-scan base-package="pagkage1[,pagkage2,-,pagkageN]"/>. 如:在base-package指明一个包 <context:component-scan base-package="cn.gacl.java"/> 表明cn.gacl.java

  • Spring-IOC容器中的常用注解与使用方法详解

    Spring是什么? Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题.它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持.Spring负责基础架构,因此Java开发者可以专注于应用程序的开发. 体系结构 核心容器(Core Container):Spring的核心容器是其他模块建立的基础,有Spring-core.Spring

  • Java基础之Spring5的核心之一IOC容器

    一.什么是IOC 1)控制反转,把创建对象和对象的调用过程交给Spring 管理. 2)使用IOC的目的,为了降低耦合度. 二.IOC的底层原理 XML解析.工厂模式.反射 三.IOC思想 基于IOC容器完成,IOC容器底层就是对象工厂. 四.Spring 提供IOC容器实现两种方式:(两个接口) (1)BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员使用 特点:加载配置文件的时候不会创建对象,在获取(使用)对象才去创建. (2)ApplicationCo

  • 详解SpringIOC容器中bean的作用范围和生命周期

    bean的作用范围: 可以通过scope属性进行设置: singleton 单例的(默认) prototype 多例的 request 作用于web应用的请求范围 session 作用于web应用的会话范围 global-session 作用于集群环境的会话范围(全局会话范围) 测试: <!-- 默认是单例的(singleton)--> <bean id="human" class="com.entity.Human"></bean&g

  • Spring实现一个简单的SpringIOC容器

    接触Spring快半年了,前段时间刚用Spring4+S2H4做完了自己的毕设,但是很明显感觉对Spring尤其是IOC容器的实现原理理解的不到位,说白了,就是仅仅停留在会用的阶段,有一颗想读源码的心于是买了一本计文柯的<Spring技术内幕>,第二章没看完,就被我扔一边了,看的那是相当痛苦,深深觉得自己资质尚浅,能力还不够,昨天在网上碰巧看到一个实现简单的SpringIOC容器的视频教程,于是跟着做了一遍,竟然相当顺利,至少每一行代码都能理解,于是细心整理了一番,放在这里. 主要思想: 提到

  • Spring创建IOC容器的方式解析

    1.直接得到 IOC 容器对象 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 封装起来: public class ApplicationContextUtil { private static ApplicationContext applicationContext = null; public ApplicationCont

  • 浅谈Spring IoC容器的依赖注入原理

    本文介绍了浅谈Spring IoC容器的依赖注入原理,分享给大家,具体如下: IoC容器初始化的过程,主要完成的工作是在IoC容器中建立 BeanDefinition 数据映射,并没有看到IoC容器对Bean依赖关系进行注入, 假设当前IoC容器已经载入用户定义的Bean信息,依赖注入主要发生在两个阶段 正常情况下,由用户第一次向IoC容器索要Bean时触发 但我们可以在 BeanDefinition 信息中通过控制 lazy-init 属性来让容器完成对Bean的预实例化,即在初始化的过程中就

  • 浅析Java的Spring框架中IOC容器容器的应用

    Spring容器是Spring框架的核心.容器将创建对象,它们连接在一起,配置它们,并从创建到销毁管理他们的整个生命周期.在Spring容器使用依赖注入(DI)来管理组成应用程序的组件.这些对象被称为Spring Beans. 容器获得其上的哪些对象进行实例化,配置和组装通过阅读提供的配置元数据的说明.配置元数据可以通过XML,Java注释或Java代码来表示.下面的图是Spring如何工作的高层次图. Spring IoC容器是利用Java的POJO类和配置元数据的产生完全配置和可执行的系统或

随机推荐