Spring实战 | Spring IOC不能说的秘密?

这篇具有很好参考价值的文章主要介绍了Spring实战 | Spring IOC不能说的秘密?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

国庆中秋特辑系列文章:

国庆中秋特辑(八)Spring Boot项目如何使用JPA

国庆中秋特辑(七)Java软件工程师常见20道编程面试题

国庆中秋特辑(六)大学生常见30道宝藏编程面试题

国庆中秋特辑(五)MySQL如何性能调优?下篇

国庆中秋特辑(四)MySQL如何性能调优?上篇

国庆中秋特辑(三)使用生成对抗网络(GAN)生成具有节日氛围的画作,深度学习框架 TensorFlow 和 Keras 来实现

国庆中秋特辑(二)浪漫祝福方式 使用生成对抗网络(GAN)生成具有节日氛围的画作

国庆中秋特辑(一)浪漫祝福方式 用循环神经网络(RNN)或长短时记忆网络(LSTM)生成祝福诗词


Spring IOC(Inversion of Control,控制反转)是 Spring 框架的核心特性之一,它通过解耦和依赖注入的方式简化了应用的组件开发和维护。在 Spring 框架中,有两个主要的 IOC 容器实现:一个是基于 XML 配置文件的 BeanFactory,另一个是基于 Java 类的 ApplicationContext。

Spring实战 | Spring IOC不能说的秘密?,spring,java,后端,开发语言

一、工作原理

这里我们以一个简单的案例来分析 Spring IOC 的工作原理。假设我们有一个简单的 Java 程序,需要用到一个数据持久层(DataAccess)和一个业务层(Service)。
首先,我们需要创建一个 Spring 配置文件(如:applicationContext.xml),在这个文件中,我们将 DataAccess 和 Service 作为 Bean 定义:

<bean id="dataAccess" class="com.example.DataAccessImpl"/>  
<bean id="service" class="com.example.ServiceImpl" property="dataAccess">  
   <property name="dataAccess" ref="dataAccess"/>  
</bean>  

在这个配置文件中,我们定义了两个 Bean:一个是 DataAccess 类型的 Bean,另一个是 Service 类型的 Bean。Service Bean 中的 dataAccess 属性通过 ref 属性指定为 DataAccess Bean。
接下来,我们需要在 Java 程序中创建一个 Spring 的 IOC 容器,并从中获取 DataAccess 和 Service Bean:

import com.example.DataAccess;  
import com.example.Service;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {  
   public static void main(String[] args) {  
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
       DataAccess dataAccess = (DataAccess) context.getBean("dataAccess");  
       Service service = (Service) context.getBean("service");
       // 使用 Service 进行业务操作  
       service.doSomething();  
   }  
}

在这个 Java 程序中,我们首先创建了一个 Spring 的 IOC 容器(ApplicationContext),然后通过 getBean 方法获取了 DataAccess 和 Service Bean。注意,由于 Service Bean 的 dataAccess 属性是通过 ref 属性指定为 DataAccess Bean,所以在获取 Service Bean 时,Spring 会自动将 DataAccess Bean 注入到 Service Bean 中。
现在,我们可以通过 Service 类的 doSomething 方法来调用 DataAccess 类的相关方法进行数据持久操作。这个过程就是 Spring IOC 的工作原理。Spring IOC 容器负责管理 Bean 的创建和管理,以及 Bean 之间的依赖关系,我们只需要关注业务逻辑的实现即可。
总结一下,Spring IOC 的核心思想是:不再由对象自己创建和管理它所依赖的对象,而是由外部(如 Spring 容器)负责注入依赖对象。这样可以大大简化对象的创建和管理,提高代码的可维护性和可扩展性。

二、具体分析

  1. 资源加载:Spring IOC 容器中的资源加载主要采用了模板设计模式和抽象工厂设计模式。在创建实例的托管和创建过程中,Spring 根据 XML 配置文件创建 Resource 对象,该对象中包含了 BeanDefinition 的信息。
// Resource 加载  
public Resource getResourceByPath(String path) {  
   if (path.startsWith("/")) {  
       path = path.substring(1);  
   }  
   Resource[] resources = getResources();  
   for (Resource resource : resources) {  
       if (resource.getPath().equals(path)) {  
           return resource;  
       }  
   }  
   return null;  
}
  1. BeanDefinition 的管理:Spring IOC 容器中的 BeanDefinition 是一个重要的组成部分,它用于描述 Bean 的定义,包括 Bean 的名称、类名、属性等信息。BeanDefinition 的管理主要通过 BeanDefinitionRegistry 和 BeanDefinitionReader 两个类实现。
// BeanDefinitionReader 读取 BeanDefinition  
public void readBeanDefinitions(Resource resource) throws BeansException, IOException {  
   if (!resource.exists()) {  
       return;  
   }  
   try (InputStream reader = resource.getInputStream()) {  
       while (reader.markSupported()) {  
           int marker = reader.mark();  
           if (marker == XMLBeanDefinitionReader.ROOT_ELEMENT_START_MARKER) {  
               // 创建 BeanDefinitionReader 对象  
               BeanDefinitionReader beanDefinitionReader = new BeanDefinitionReader(this);  
               // 开始解析 XML 文件中的 BeanDefinition  
               beanDefinitionReader.parse(reader);  
           } else if (marker == XMLBeanDefinitionReader.ROOT_ELEMENT_END_MARKER) {  
               // 解析结束  
               break;  
           }  
       }  
   }  
}
  1. Bean 的创建和管理:Spring IOC 容器中的 Bean 创建和管理主要通过 BeanFactory 类实现。BeanFactory 类包含了创建 Bean、获取 Bean、删除 Bean 等方法,它是 Spring IOC 容器的核心部分。
// BeanFactory 创建 Bean  
public Object getBean(String name) throws BeansException {  
   // 根据 Bean 名称获取 BeanDefinition  
   BeanDefinition beanDefinition = getBeanDefinition(name);  
   // 如果 BeanDefinition 不存在,抛出异常  
   if (beanDefinition == null) {  
       throw new NoSuchBeanDefinitionException(name);  
   }  
   // 创建 Bean  
   Object bean = createBean(name, beanDefinition);  
   // 返回 Bean  
   return bean;  
}
  1. 依赖注入:Spring IOC 容器中的依赖注入主要通过 DependencyAutowire 和 PropertyAutowire 两个类实现。DependencyAutowire 类用于自动注入依赖,而 PropertyAutowire 类用于自动注入属性。
// DependencyAutowire 注入依赖  
public void setDependency(String propertyName, @Qualifier @Nullable String[] qualifiedClassNames) {  
   // 获取 BeanDefinition  
   BeanDefinition beanDefinition = getBeanDefinition(propertyName);  
   // 如果 BeanDefinition 不存在,抛出异常  
   if (beanDefinition == null) {  
       throw new NoSuchBeanDefinitionException(propertyName);  
   }  
   // 获取依赖的 Bean  
   @Qualifier("'" + beanDefinition.getBeanClassName() + "'")  
   @Autowired  
   Object dependency = getBeanFactory().getBean(propertyName, Object.class);  
   // 设置依赖  
   setter.setValue(this, dependency);  
}
  1. 生命周期管理:Spring IOC 容器中的生命周期管理主要通过 Lifecycle 和 LifecycleCallback 两个接口实现。Lifecycle 接口定义了 Bean 的生命周期方法,如 start、stop 等;LifecycleCallback 接口则是一个回调接口,用于在 Bean 的生命周期方法执行前后执行特定的逻辑。
// Lifecycle 接口  
public interface Lifecycle {  
   void start() throws BeansException;  
   void stop() throws BeansException;  
   boolean isStarted();  
   boolean isStopped();  
   void destroy() throws BeansException;  
}

三、核心功能分析

由于 Spring IOC 核心代码较长,无法在这里全部展示。但我可以简要介绍一下 Spring IOC 的核心部分,并提供部分关键代码示例。

  1. BeanFactory 的创建:
    BeanFactory 是 Spring IOC 容器的基本实现,它负责管理 Bean 的创建和管理。创建过程主要包括以下几个步骤:
  • 读取 Spring 配置文件(如 applicationContext.xml),解析其中的 Bean 定义;
  • 创建一个 BeanDefinitionRegistry,用于存储解析后的 BeanDefinition;
  • 创建一个 BeanFactoryInstance,用于封装 BeanDefinitionRegistry 和其他 BeanFactory 的实例;
  • 调用 BeanFactoryInstance 的 getObjectForBeanName 方法,根据 BeanName 获取对应的 Bean 定义;
  • 通过 BeanDefinition 的 getBean 方法创建 Bean 实例;
  • 将 Bean 实例添加到 BeanFactory 的 singletonObjects 中,以 BeanName 为键。
    以下是创建 BeanFactory 的示例代码:
public class BeanFactoryImpl implements BeanFactory {  
   //... 省略其他代码...
   @Override  
   protected void createBeanFactory(String name, BeanDefinitionRegistry registry) throws BeansException {  
       // 创建并初始化一个 DefaultListableBeanFactory 实例  
       DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();  
       beanFactory.setBeanDefinitionRegistry(registry);  
       beanFactory.setResourceAccess(new ClassPathResource(name, getClassLoader()));  
       beanFactory.setEnvironment(this.environment);  
       beanFactory.setApplicationContextName(name);  
       beanFactory.setParentBeanFactory(this);  
       beanFactory.setSingletonObjects(new ConcurrentHashMap<String, Object>());  
       beanFactory.setDefaultSingletonBeanName(name);  
       beanFactory.registerBeanDefinition(new RootBeanDefinition(beanFactory, name));  
   }  
}
  1. Bean 的生命周期:
    Bean 的生命周期主要包括以下几个阶段:
  • 实例化:根据 BeanDefinition 创建 Bean 实例;
  • 属性填充:将 BeanDefinition 中的属性值设置到 Bean 实例上;
  • 初始化:调用 Bean 的初始化方法,进行相关设置;
  • 依赖注入:将 Bean 的依赖关系注入到 Bean 实例上;
  • 销毁:当 Bean 没有引用时,调用 Bean 的 destroy 方法进行销毁。
    以下是 Bean 生命周期的示例代码:
public class BeanFactoryImpl implements BeanFactory {  
   //... 省略其他代码...
   @Override  
   protected Object createBean(String name, BeanDefinition beanDefinition, Object[] args) throws BeansException {  
       // 根据 BeanDefinition 创建 Bean 实例  
       Object bean = beanDefinition.getBean();
       // 属性填充  
       for (PropertyValue propertyValue : beanDefinition.getPropertyValues()) {  
           bean = propertyValue.resolve(bean);  
       }
       // 初始化  
       bean = beanDefinition.initialize(bean);
       // 依赖注入  
       if (bean instanceof ConfigurableBeanFactory) {  
           ((ConfigurableBeanFactory) bean).mergeBeanDefinitions(beanDefinition.getResourceDescription());  
       }
       // 将 Bean 添加到 singletonObjects 中,以 BeanName 为键  
       synchronized (this.singletonObjects) {  
           this.singletonObjects.put(name, bean);  
       }
       return bean;  
   }  
}
  1. 依赖注入:
    Spring IOC 容器通过依赖注入(Dependency Injection,DI)的方式将 Bean 的依赖关系注入到 Bean 实例上。依赖注入主要有两种方式:构造器注入和 setter 方法注入。
    以下是依赖注入的示例代码:
public class BeanFactoryImpl implements BeanFactory {  
   //... 省略其他代码...
   @Override  
   protected Object createBean(String name, BeanDefinition beanDefinition, Object[] args) throws BeansException {  
       //... 省略其他代码...
       // 依赖注入  
       if (bean instanceof ConfigurableBeanFactory) {  
           ((ConfigurableBeanFactory) bean).mergeBeanDefinitions(beanDefinition.getResourceDescription());  
       }
       //... 省略其他代码...  
   }  
}

以上是 Spring IOC 核心代码的简要分析和示例。要了解更多关于 Spring IOC 的详细信息,建议参考 Spring 官方文档和相关教程。文章来源地址https://www.toymoban.com/news/detail-712746.html

到了这里,关于Spring实战 | Spring IOC不能说的秘密?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring教程11】Spring框架实战:IOC/DI注解开发管理第三方bean的全面深入详解

    欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 纯注解开发模式下的依赖注入和读取properties配置文件》 前面定义bean的时

    2024年02月04日
    浏览(42)
  • spring框架,以及和spring框架相关的Java面试题和spring ioc的注入方式

    目录 一.spring来源,以及介绍 1.spring诞生的背景 2.spring框架 介绍 3.spring框架在使用中的优点以及不足 3.1优点  3.2不足 3.3总结 4.为什么要使用spring  二.将spring框架部署在IDEA中  1.替换pom.xml  2.构建spring所需要的xml文件 三.spring的三种注入方式 0.定义需要的类,方法 1.方法注入

    2024年02月12日
    浏览(36)
  • 【Java面试】Spring中的IOC和AOP

    IOC:控制反转也叫依赖注入。利用了工厂模式 将对象交给容器管理,你只需要在spring配置文件总配置相应的bean,以及设置相关的属性,让spring容器来生成类的实例对象以及管理对象。在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的

    2024年02月10日
    浏览(35)
  • 【Java EE】Spring核心思想(一)——IOC

    通过前⾯的学习, 我们知道了Spring是⼀个开源框架, 他让我们的开发更加简单. 他⽀持⼴泛的应⽤场 景, 有着活跃⽽庞⼤的社区, 这也是Spring能够⻓久不衰的原因. 但是这个概念相对来说, 还是⽐较抽象. 我们⽤⼀句更具体的话来概括Spring, 那就是: Spring 是包含了众多⼯具⽅法的

    2024年04月23日
    浏览(38)
  • 【Spring教程十】Spring框架实战:全面深入详解IOC/DI之--纯注解开发模式下的依赖注入&&注解读取properties配置文件

    欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 全面深入详解IOC/DI注解开发》 Spring为了使用注解简化开发,并没有提供

    2024年02月04日
    浏览(44)
  • java八股文面试[Spring]——如何实现一个IOC容器

            IOC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出 松耦合 ,更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IOC容器后,把 创建和查找依赖对象 的控制

    2024年02月10日
    浏览(36)
  • 【Java学习】 Spring的基础理解 IOC、AOP以及事务

        官网: https://spring.io/projects/spring-framework#overview     官方下载工具: https://repo.spring.io/release/org/springframework/spring/     github下载: https://github.com/spring-projects/spring-framework     maven依赖: 1.spring全家桶的结构构图:              最下边的是测试单元   其中spring封装

    2024年02月09日
    浏览(29)
  • Spring IOC容器:让Java对象的管理和配置更简单

    在Java开发中,我们经常需要创建和使用各种Java对象,例如实体类,服务类,控制器类等。这些对象之间通常存在着一定的依赖关系,例如一个服务类可能需要调用另一个服务类或一个数据访问类的方法。为了创建和使用这些对象,我们通常需要做以下几件事: 在代码中通过

    2024年02月11日
    浏览(29)
  • Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性

    💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:Java Spring IoCDI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性 🎉欢迎大家点赞👍评论📝收藏⭐文章 我们一下要学习的内容都是为了实现⾼内聚低耦合来进行的 软件设计原则:⾼内聚低耦合. ⾼内聚指

    2024年04月15日
    浏览(38)
  • Java面试题:你知道Spring的IOC吗?那么,它为什么这么重要呢?

    Spring的IOC(控制反转)是一种设计模式,它允许开发者将对象的创建和管理交给Spring框架来完成。在Spring中,IOC允许开发者将对象依赖关系从代码中分离出来,从而使代码更加灵活、可重用和易于管理。 IoC 全称Inverse of Control( 反向控制或控制反转 )。 在类和类之间存在控

    2024年04月28日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包