SpringIOC机制详解

news2024/12/23 19:38:58

一、IOC概述及作用

(一)IOC的简介,设计思想

SpringIOC:IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”。

IOC这个概念简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部透明的,从而降低了解决问题的复杂度,而且可以灵活的被重用和扩展。

IOC理论提出的观点大体是这样的:借助于第三方实现具有依赖关系的对象之间的解耦。

img编辑

由于引进了中间位置“第三方”,也就是IOC容器,使得A、B、C、D这四个对象没有了耦合关系,齿轮之间的传动全部依靠IOC容器,全部对象的控制权上交给IOC容器,所以IOC容器成了整个系统的关键核心,它起到一个“粘合剂”的作用,把系统中所有对象粘合在一起发挥作用。

img编辑

当把图中的IOC容器拿掉,可以发现A、B、C、D这四个 对象之间没有耦合关系。这样的话,当我们去实现A的时候,根本无需去考虑其他几个对象,对象之间的依赖关系已经讲到了最低程度。

(二)IOC作用

IOc本质上就是一个大工程,大容器。主要作用就是创建和管理对象的依赖关系,削减计算机程序的耦合(解除我们代码间的依赖关系),提高程序的可扩展性和可维护性。

二、SpringIOC入门案例前期准备

(一)构建maven工程,添加Spring框架的依赖

<properties>
    <spring.version>5.2.5.RELEASE</spring.version>
</properties>
<!--导入spring的context坐标,context依赖core、beans、expression aop-->
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
</dependencies>

(二)创建持久层接口和实现类

public interface UserDao {
    public void save();
}
​
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("userDao save method running...... ");
    }
}

(三)创建业务层接口和实现类

public interface UserService {
    public void saveService();
}
​
public class UserServiceImpl implements UserService {
    @Override
    public void saveService() {
        System.out.println("userSerivce save method running......");
    }
}

(四)在resources文件夹中创建一个任意名称的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/springbeans.xsd">
</beans>

(五)让Spring管理资源,在配置文件中配置service和dao

<?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">
​
    <!--配置userDaoImpl-->
    <bean id="userDao" class="com.ujiuye.dao.impl.UserDaoImpl"></bean>
    <!--配置userServiceImpl-->
    <bean id="userService" class="com.ujiuye.service.UserServiceImpl"></bean>
</beans>

(六)测试IOC配置是否成功

@Test
public void test1(){
    //1:获得spring IOC容器对象:
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
​
    //2:从容器当中根据id获得UserDaoImpl 对象,执行userDao对象的save方法
    UserDao userDao = (UserDao) applicationContext.getBean("userDao");
    userDao.save();
​
    //3:从容器当中根据id获得UserServiceImpl 对象,执行userService对象的saveService
方法
    UserService userService = (UserService)applicationContext.getBean("userService");
    userService.saveService();
}

运行结果:

img编辑

三、Spring基于XML的IOC细节

(一)IOC配置文件详解:配置标签书写规范,配置标签的属性

bean标签:用于配置对象交给Spring来创建

默认情况下他会调用类中无参数的构造器,如果没有无参数构造器则不能创建成功。

基本属性:

id:Bean实例对象在Spring容器中的唯一标识

class:Bean的全限定类名

(二)SpringIOC机制源码解析

1、IOC容器解析

IOC思想基于IOC容器完成,IOC容器底层就是对象工厂,Spring中工厂的类结构图如下;

img编辑

(1)BeanFactory

IOC容器的基本实现,是Spring内部使用的接口,不提供开发人员使用,加载配置文件时,不会创建对象,在获得(使用)对象时才采取创建对象。

(2)HierarchicalBeanFactory

这个工厂接口非常简单,实现了Bean工厂的分层。工厂接口也是继承自BeanFactory,也是一个二级接口,相对于父接口,他只是扩展了一个重要的功能———工厂分层

(3)AutowireCapableBeanFactory

该接口有自动配置能力,需要注意的是,ApplicationContext接口并实现此接口,因为应用代码很少用到此功能,如果确实需要的话,可以调用ApplicationContext getAutowireCapableBeanFactory方法,来获取此接口的实例。

(4)ListableBeanFactory

获取bean时,Spring鼓励使用这个接口定义的api,如查看bean的个数、获取某一类型Bean的配置名、查看容器中是否包括某一Bean等方法。

(5)ApplicationContext

BeanFactory接口的子接口,提供更多强大的功能,一般由开发人员使用。接口提供了bean基础性操作同时,扩展了国际化等功能。ApplicationContext接口在加载配置文件时候就会配置文件当中的对象进行创建,存放IOC容器当中

(6)AnnotationConfigApplicationContext

当使用注解配置容器对象时,需要使用此类来创建spring容器。他用来读取注解。

(7)ClassPathXmlApplicationContext

它是从类的根路径下加载配置文件

(8)FileSystemXmlApplicationContext

它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。

2、IOC容器底层bean初始化过程

img编辑

(1)BeanFactionPostProcessor

作用:定义了在bean工厂对象创建后,bean对象创建前执行的动作,用于对工厂进行创建后业务处理

运行时机:操作用于对工厂进行处理,仅运行一次

(2) BeanPostProcessor

作用:定义了所有bean初始化前后进行的统一动作,用于对bean进行创建前业务处理与创建后业务处理

运行时机:当前操作伴随着每个bean的创建过程,每次创建bean均运行该操作。

(3)InitializingBean

作用:定义了每个bean的初始化前进行的动作,属于非统一性动作,用于对bean进行创建前业务处理。

运行时机:当前操作伴随着任意一个bean的创建过程,保障其个性化业务处理

四、手动实现自己的IOC容器

(一)分析IOC实现思路

img编辑

(二)IOC原理实现—环境搭建:构建maven工程,引入依赖

<properties>
        <spring.version>5.2.5.RELEASE</spring.version>
    </properties>
​
    <dependencies>
        <!--导入spring的context坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--导入junit单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

(三)设计接口和类以及编写配置文件

//设定UserDao接口
public interface UserDao {
    public void save();
}
//设定UserDao接口实现类
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("userDao save method running...... ");
    }
}

配置文件:

<!--配置userDaoImpl-->
<bean id="userDao" class="com.ujiuye.dao.impl.UserDaoImpl"></bean>

(四)使用xml技术解析配置文件

<!--引入dom4J-->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>

/**
* 创建自己的工厂类
*/
public class MyBeanFactory {
​
    //创建一个map集合,模拟IOC容器
    private static Map<String,Object> map = new HashMap<>();
​
    static{
        try {
            //使用dom4J 解析xml文件:
            //第一步:获得一个解析器:
            SAXReader reader = new SAXReader();
            //第二: 读取外部的配置文件:
            String path = "src/main/resources/applicationContext.xml";
            //第三: 读取了整个文档对象
            Document document = reader.read(path);
            //第四: 获得根节点:
            Element rootElement = document.getRootElement();//beans
            //第五: 获得根节点下的所有的bean 标签对应的节点:
            List<Element> bean = rootElement.elements("bean");// bean
            for (Element element : bean) {
                //获得id属性对应的值:
                String id1 = element.attributeValue("id");
                //获得class属性对应的值:【全限定类名】
                String aClass = element.attributeValue("class");//获得class对应的值: 全限定类名。
                //通过反射创建对象:
                Class clz = Class.forName(aClass);
                Object object = clz.newInstance();
                //存容器 id做key,创建出来的对象value
                map.put(id1,object);
            }
​
        } catch (Exception e) {
            e.printStackTrace();
    }
}

/**
* 根据id从容器当中获得对象
* @param id id的名称
* @return 返回Object类型对象
*/
public static Object getBean(String id){
    Object o = map.get(id);
    return o;
    }
}

(五)编写测试文件,展示测试结果

@Test
public void testMyFactory(){
    //1:创建工厂对象
    MyBeanFactory factory =new MyBeanFactory();
    //2:从容器当中根据id获得对象
    UserDao userDao = (UserDao) factory.getBean("userDao");
    System.out.println(userDao);
    userDao.save();
}

五、Spring管理bean细节

(一)bean实例化方式

1、构造方法的方式

(1)创建User类

public class User implements Serializable {
    public User(){
        System.out.println("user created...");
    }
}

(2)配置Spring容器管理user类型对象

<!--配置user对象-->
<bean id="user" class="com.ujiuye.pojo.User"></bean>

(3)测试容器实例化User对象是否成功)

@Test
public void testUser(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    User user = (User) context.getBean("user");
    System.out.println(user);
}

2、静态工厂方式

(1)创建静态工厂ItemFactory

public class ItemFactory {
    //静态方法返回实例bean
    public static User createUser(){
        System.out.println("static method running create bean ......");
        return new User();
    }
}

(2)配置Spring容器管理User类型对象

<!--静态工厂实例化对象-->
<bean id="user" class="com.ujiuye.factory.ItemFactory"></bean>

(3)测试容器实例化User对象是否成功

@Test
public void testItemFactory(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    User user = (User) context.getBean("user");
    System.out.println(user);
}

3、实例工厂方式

(1)创建实例工厂NewItemFactory

public class NewItemFactory {
    //工厂的非静态方法返回bean实例
    public User createUser(){
        System.out.println("Dynamic method running create bean ......");
        return new User();
    }
}

(2)配置Spring容器管理NewItemFactory类型对象

​
<!--实例工厂-->
<bean id="itemFactory" class="com.ujiuye.factory.NewItemFactory"></bean>
<bean id="user" factory-bean="itemFactory" factory-method="createUser"></bean>


​

(3)测试容器实例化User对象是否成功

@Test
public void testNewItemFactory(){
    ApplicationContext context =
    new ClassPathXmlApplicationContext("applicationContext.xml");
    User user = (User) context.getBean("user");
    System.out.println(user);
}

(二)bean作用域

1、bean作用域介绍

所谓Bean的作用域其实就是指Spring给我们创建出的对象的存活范围,在配置文件中通过bean的scope属性指定

scope:指对象的作用范围,取值如下:

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

2、bean作用域的解析

(1)当**scope的取值为singleton时**

Bean的实例化个数:1个

Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例

(2)当**scope的取值为prototype时**

Bean的实例化个数:多个

Bean的实例化时机:当调用getBean()方法时实例化Bean

(3)当**Scope的取值为其他值**

scope指定为其他值,需要在特定的环境下使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/702269.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 设计模式实战系列—工厂模式

在 Java 开发中&#xff0c;对象的创建是一个常见的场景&#xff0c;如果对象的创建和使用都写在一起&#xff0c;代码的耦合度高&#xff0c;也不利于后期的维护。我们可以使用工厂模式来解决这个问题&#xff0c;工厂模式是一个创建型模式&#xff0c;将对象的创建和使用分离…

树莓派使用Nginx 搭建轻量级网站远程访问

文章目录 1. Nginx安装2. 安装cpolar3.配置域名访问Nginx4. 固定域名访问5. 配置静态站点 转载自cpolar极点云文章&#xff1a;树莓派使用Nginx 搭建轻量级网站远程访问 安装 Nginx&#xff08;发音为“engine-x”&#xff09;可以将您的树莓派变成一个强大的 Web 服务器&#…

AMEYA360报道:瑞萨电子坐上MCU头把交椅背

综合IC Insights和拓墣产业研究院多方数据来看&#xff0c;2020年之后全球MCU市场增长动力强劲&#xff0c;尤其是汽车MCU市场&#xff0c;有着爆发的态势。具体来看&#xff0c;2022年全球MCU市场规模达到215亿美元&#xff0c;2021年-2026年期间市场的年复合增长率预计将达到…

Java性能权威指南-总结21

Java性能权威指南-总结21 Java EE性能调优对象序列化transient字段覆盖默认的序列化压缩序列化数据 Java EE性能调优 对象序列化 不同系统间的数据交换可以使用XML、JSON和其他基于文本的格式。Java进程间交换数据&#xff0c;通常就是发送序列化后的对象状态。尽管序列化在J…

记一次 .NET 使用 csreids 连接 Redis 超时问题

背景: 使用windows server 2016 , IIS 部署的程序运行一段时间后出现异常, Redis 部署在内网其他服务器; 通过windows 事件查看器发现一些错误日志 , CSRedis.Internal.IO.RedisSocketException: Connect to server timeout 大概意思为连接redis服务 超时; 错误 2023/6/29 11…

通过 Python 控制 AWG70001 发送任意波

0. 实验准备 泰克 AWG70001 一台电脑 一根网线 使用网线连接 AWG70001 和电脑&#xff0c;并且配置 IP 在同一网段下 1. 环境要求 vxi11 numpy struct matplotlib 没有的库可以使用下面的命令安装 pip install vxi11 pip install numpy pip install struct pip install matp…

苹果iphone如何备份整个手机 苹果怎么查备份的照片

手机上的数据变得越来越重要&#xff0c;大家也越来越注重数据安全。如果手机设备丢失的话&#xff0c;不仅是设备的丢失&#xff0c;还是数据的丢失。因此&#xff0c;备份数据就显得很重要。那么&#xff0c;iphone如何备份整个手机&#xff0c;苹果怎么查备份的照片&#xf…

C++day4

2、 #include <iostream>using namespace std;class Person { private:int age;int *p; public://无参构造Person():p(new int(89)){age 18;}//有参构造Person (int age,int num){this->age age;this-> p new int(num);}//拷贝构造函数(深度拷贝)Person(Person …

NTP时钟服务器推荐-国内时间服务器顶尖设备

电子钟时间服务器在物联网应用中起到了关键的作用&#xff0c;它能够为各种智能设备提供准确的时间参考&#xff0c;确保设备之间的协同工作和数据的准确传输。无论是智能家居、智能工厂还是智慧城市&#xff0c;电子钟时间服务器都是不可或缺的一部分。 一、产品卖点 时间服…

启动spring boot项目时加载配置文件报错的问题

最近把电脑重置了一下&#xff0c;然后重新安装各种软件&#xff0c;从gitee拉去项目到本地运行时居然启动报错了 Failed to load property source from file:/D:/program/IdeaProjects/layui/target/classes/application.yml 这是加载配置文件的时候失败了&#xff0c;提示一堆…

Multiple HTTP implementations were found on the classpath错误的解决方法

当我们的项目中集成了多个AWS相关Jar包时,有可能就会遇到这个错误: 错误信息: There is an issue with the connector Code: InvalidInput.InvalidConnectorConfiguration Message: The connector configuration is invalid. Message: Multiple HTTP implementations were f…

自定义MVC架构【上】

目录 一、前言 1.什么是MVC架构 2.使用MVC架构的好处 3.MVC架构与三层架构的区别 4.MVC架构的思路 二、自定义MVC 1.最初版本 2.进阶版 3.反射优化版 4.反射增强版 一、前言 1.什么是MVC架构 MVC架构&#xff08;Model-View-Controller&#xff09;&#xff0c;即模…

【MSP432电机驱动设计—下篇】霍尔编码器测车轮运行距离与M/T综合公式法测速概念

开发板型号为MSP432P401r 今日得以继续我的MSP432电赛速通之路&#xff0c;本篇使用MSP432编程学习霍尔编码器M/T公式法测速概念&#xff0c;最终实现用外部中断方式测得小车行走路程&#xff0c;文章学习讲解原理、附上实例实践、附上关键代码、附上…

微信月活破10亿,安全性靠谁来支撑?

&#x1f449;腾小云导读 微信作为月活过10亿的国民级应用&#xff0c;其安全能力备受关注。值得注意的是&#xff0c;没有足够的特征数据&#xff0c;安全策略将是"无根之木&#xff0c;无源之水"。微信安全数据仓库作为安全业务的特征数据存储中心&#xff0c;每天…

【C/C++】解析 类成员属性

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

JVM类加载双亲委派-JVM(二)

上篇文章说了java类的加载&#xff0c;验证、准备、解析、初始化。类的初始化必须是类加载完才执行&#xff0c;所以类的构造方法初始化是在静态方法之后执行。 JVM类加载机制-JVM&#xff08;一&#xff09; 一、类加载和双亲委派机制 前面类加载主要通过类加载器实现&…

JavaWeb小记——登录、注册

目录 登录项目 步骤 1.首先写一个前台页面&#xff0c;一个form表单——login.jsp 2.后台获取前台输入的参数&#xff0c;并作校验 3.写一个JDBC工具类&#xff0c;用来连接数据库&#xff0c;本案例使用Druid连接池 4.写一个登录工具类&#xff0c;在数据库中查询数据&…

【云原生】k8s的pod基础(上)

1.pod的相关知识 1.1 pod的基础概念 pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是用绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&#xff0c;用于管…

C++面试需求

一.auto 1.介绍&#xff1a; auto 是一个用于类型推导的关键字。它允许变量的类型在编译时根据其初始化值自动推断 例子&#xff1a; &#xff08;1&#xff09;自动类型推导变量 // C program to demonstrate working of auto // and type inference#include <bits/std…

shell正则入门

1.系统通配符 * #所有 . #当前目录 .. #当前目录的上一级目录 - #当前目录的上一次所在的目录 ~ #家目录 # #注释&#xff0c;超级管理员的命令行提示符 $ #引用变量&#xff0c;普通用户的命令行提示符 ? #匹配任意…