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

国庆中秋特辑系列文章

国庆中秋特辑(八)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 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 的生命周期方法,如 startstop 等;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 的创建和管理。创建过程主要包括以下几个步骤
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 的生命周期主要包括以下几个阶段
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://blog.csdn.net/superdangbo/article/details/133775504

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_19761.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注