当前位置: 首页 > news >正文

Spring IoC 的实现机制

案例一:

Spring 中的 IoC 的实现原理就是工厂模式加反射机制。我们先使用一个简单的案例理解一下:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;// 定义一个水果接口,包含吃的方法
public interface Fruit {// 抽象方法:吃public abstract void eat();
}// 苹果类实现Fruit接口
public class Apple implements Fruit {// 实现eat方法public void eat() {System.out.println("Apple");}
}// 橙子类实现Fruit接口
public class Orange implements Fruit {// 实现eat方法public void eat() {System.out.println("Orange");}
}// 安全工厂类,用于根据类名动态创建Fruit对象
public class SafeFactory {/*** 根据指定的类名创建Fruit对象** @param className 类名,必须是实现了Fruit接口的类的全限定名* @return 创建的Fruit对象,如果出现异常则抛出* @throws ClassNotFoundException 如果找不到指定的类* @throws IllegalAccessException 如果访问类的构造函数时出错* @throws InstantiationException 如果无法实例化类* @throws NoSuchMethodException 如果类没有默认构造函数* @throws InvocationTargetException 如果调用构造函数时出错*/public static Fruit getInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {// 检查类名是否为null或空字符串if (className == null || className.trim().isEmpty()) {throw new IllegalArgumentException("类名不能为空");}// 确保类名符合Java类名的命名规则if (!className.matches("^[a-zA-Z_$][a-zA-Z0-9_$]*$")) {throw new IllegalArgumentException("无效的类名:" + className);}// 加载指定的类,并检查是否实现了Fruit接口Class<?> clazz = Class.forName(className);if (!Fruit.class.isAssignableFrom(clazz)) {throw new IllegalArgumentException("指定的类未实现Fruit接口:" + className);}// 获取类的所有声明的构造函数,确保只有一个公共构造函数Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();if (declaredConstructors.length != 1) {throw new IllegalStateException("指定的类必须有一个默认构造函数:" + className);}// 设置构造函数的访问权限,并实例化对象declaredConstructors[0].setAccessible(true);return (Fruit) declaredConstructors[0].newInstance();}
}// 客户端类,演示如何使用工厂类
public class Client {public static void main(String[] args) {try {// 使用工厂类创建Apple对象Fruit f = SafeFactory.getInstance("Apple"); // 使用全限定类名以确保正确性if (f != null) {f.eat(); // 调用eat方法}} catch (Exception e) {e.printStackTrace();}}
}

        这个简单的案例模拟了Spring IoC的基本原理,但请注意,Spring的实现更为复杂,包括对XML或注解配置的支持、自动扫描、类型安全的依赖注入、AOP支持等。在实际的Spring框架中,这些功能都是通过ApplicationContext来提供的,它可以加载配置,管理Bean的生命周期,以及处理依赖注入。

案例二:

下面我们再写一个Spring IoC的实现机制的步骤,以及一个简单的XML配置文件案例:
1. Bean定义:
        Spring 需要知道如何创建和配置每个对象,这通常是通过XML配置文件完成的,或者通过注解(@Component, @Service, @Repository, @Controller 等)。
2. Bean工厂:
        Spring 使用 BeanFactory 作为基础容器,它负责创建、配置和管理Bean。更高级别的 ApplicationContext 扩展了 BeanFactory,提供了更多功能,如消息源、国际化支持等。
3. 反射:
        Spring 使用Java的反射机制来根据Bean定义创建对象。反射允许在运行时动态创建对象并调用其方法。
4. 依赖注入:
        Spring 通过依赖注入将对象之间的依赖关系解耦。它可以在构造函数、setter方法或属性级别注入依赖。
5. 配置元数据解析:
        Spring 读取XML配置文件或其他元数据源,解析Bean定义并构建Bean的内部表示。
6. 实例化和初始化:
        当需要一个Bean时,Spring容器使用反射创建一个新的实例,然后根据Bean定义注入所有依赖。

以下是一个简单的XML配置文件案例,展示了如何定义和配置Bean:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义一个名为myService的Bean --><bean id="myService" class="com.example.MyService"><!-- 使用setter注入依赖 --><property name="myDependency" ref="myDependencyBean"/></bean><!-- 定义一个名为myDependencyBean的Bean --><bean id="myDependencyBean" class="com.example.MyDependency"/></beans>

在这个例子中,MyService 类有一个名为 myDependency 的依赖,它将通过 myDependencyBean Bean注入。Spring 会自动调用 MyService 类中的 setMyDependency 方法来设置这个依赖。

7. 使用Bean:
        在应用程序代码中,你可以通过 ApplicationContext 获取Bean实例,如下所示:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyService myService = (MyService) context.getBean("myService");
myService.doSomething();

这里,ClassPathXmlApplicationContext 从类路径加载配置文件 applicationContext.xml,然后通过 getBean 方法获取 myService Bean 的实例。

通过这种方式,Spring IoC容器管理了对象的生命周期和依赖关系,使得应用程序的组件可以松散耦合。

相关文章:

  • Linux用户权限管理小实验002
  • C++牛客周赛43题目分享(3)小红平分糖果,小红的完全平方数,小苯的字符串变化,小红的子数组排列判断
  • 【云原生】kubernetes中的认证、权限设置--RBAC授权原理分析与应用实战
  • 虚拟机Ubuntu 22.04上搭建GitLab操作步骤
  • 黑客团伙利用Python、Golang和Rust恶意软件袭击印国防部门;OpenAI揭秘,AI模型如何被用于全球虚假信息传播? | 安全周报0531
  • 《异常检测——从经典算法到深度学习》29 EasyTSAD: 用于时间序列异常检测模型的工业级基准
  • 深入分析 Android Activity (二)
  • 软考系统集成项目管理工程师第7章思维导图发布
  • 探索AI去衣技术中的反射应用
  • FreeRTOS基础(三):动态创建任务
  • 面试题:计算机网络中的七四五是什么?
  • pytorch学习笔记3
  • Vue:现代前端开发的首选框架-【高级特性篇】
  • JAVA:异步任务处理类CompletableFuture让性能提升一倍
  • 如何设置手机的DNS
  • JavaScript 如何正确处理 Unicode 编码问题!
  • Apache Spark Streaming 使用实例
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • JDK 6和JDK 7中的substring()方法
  • Magento 1.x 中文订单打印乱码
  • October CMS - 快速入门 9 Images And Galleries
  • scrapy学习之路4(itemloder的使用)
  • Shell编程
  • Vim Clutch | 面向脚踏板编程……
  • Vue官网教程学习过程中值得记录的一些事情
  • WePY 在小程序性能调优上做出的探究
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 讲清楚之javascript作用域
  • 利用DataURL技术在网页上显示图片
  • 前端相关框架总和
  • 使用API自动生成工具优化前端工作流
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 一起参Ember.js讨论、问答社区。
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • ​configparser --- 配置文件解析器​
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ###STL(标准模板库)
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (+4)2.2UML建模图
  • (C++)八皇后问题
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (学习日记)2024.01.09
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)mysql使用Navicat 导出和导入数据库
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • .bat批处理(一):@echo off
  • .Net CF下精确的计时器
  • .Net环境下的缓存技术介绍
  • .NET开发者必备的11款免费工具
  • .Net中的集合
  • @GetMapping和@RequestMapping的区别
  • @ModelAttribute 注解