{"id":13635435,"url":"https://github.com/houbb/ioc","last_synced_at":"2025-04-10T18:31:27.212Z","repository":{"id":57720087,"uuid":"219960421","full_name":"houbb/ioc","owner":"houbb","description":"The java ioc framework（从零开始手写模拟 spring Ioc 框架）","archived":false,"fork":false,"pushed_at":"2022-11-30T04:44:31.000Z","size":307,"stargazers_count":35,"open_issues_count":2,"forks_count":19,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-25T02:51:34.941Z","etag":null,"topics":["autowired","di","guice","inject","ioc","spring"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/houbb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGE_LOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-06T09:33:36.000Z","updated_at":"2025-03-03T07:50:29.000Z","dependencies_parsed_at":"2023-01-22T06:45:48.024Z","dependency_job_id":null,"html_url":"https://github.com/houbb/ioc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houbb%2Fioc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houbb%2Fioc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houbb%2Fioc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houbb%2Fioc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/houbb","download_url":"https://codeload.github.com/houbb/ioc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248271722,"owners_count":21075800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autowired","di","guice","inject","ioc","spring"],"created_at":"2024-08-02T00:00:45.536Z","updated_at":"2025-04-10T18:31:25.885Z","avatar_url":"https://github.com/houbb.png","language":"Java","funding_links":[],"categories":["测试"],"sub_categories":["客户端"],"readme":"# IoC\n\n[Ioc](https://github.com/houbb/ioc) 是一款 spring ioc 核心功能简化实现版本，便于学习和理解原理。\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.houbb/ioc/badge.svg)](http://mvnrepository.com/artifact/com.github.houbb/ioc)\n\n## 创作目的\n\n使用 spring 很长时间，对于 spring 使用非常频繁，实际上对于源码一直没有静下心来学习过。\n\n但是 spring 源码存在一个问题，那就是过于抽象，导致学习起来成本上升。\n\n所以本项目由渐入深，只实现 spring 的核心功能，便于自己和他人学习 spring 的核心原理。\n\n## spring 的核心 \n\nSpring 的核心就是 spring-beans，后面的一切 spring-boot，spring-cloud 都是建立在这个地基之上。\n\n当别人问你 spring 的时候，希望你可以谈谈自己对于 spring ioc 自己更深层的见解，而不是网上人云亦云的几句话。\n\n# 什么是 IOC\n\n控制反转（Inversion of Control，缩写为IoC），是面向对象编程中的一种设计原则，可以用来减低计算机代码之间的耦合度。\n\n其中最常见的方式叫做依赖注入（Dependency Injection，简称DI）。\n\n通过控制反转，对象在被创建的时候，由一个调控系统内所有对象的外界实体，将其所依赖的对象的引用传递给它。\n\n也可以说，依赖被注入到对象中。\n\n## 为什么需要 IOC\n\nIoC 是解耦的一种方法。\n\n我们知道Java 是一门面向对象的语言，在 Java 中 Everything is Object，我们的程序就是由若干对象组成的。\n\n当我们的项目越来越大，合作的开发者越来越多的时候，我们的类就会越来越多，类与类之间的引用就会成指数级的增长。\n\n![mess](https://segmentfault.com/img/remote/1460000013000748?w=370\u0026h=240)\n\n这样的工程简直就是灾难，如果我们引入 Ioc 框架。\n\n由框架来维护类的生命周期和类之间的引用。\n\n我们的系统就会变成这样：\n\n![manager](https://segmentfault.com/img/remote/1460000013000749?w=370\u0026h=247)\n\n这个时候我们发现，我们类之间的关系都由 IoC 框架负责维护类，同时将类注入到需要的类中。\n\n也就是类的使用者只负责使用，而不负责维护。\n\n把专业的事情交给专业的框架来完成，大大的减少开发的复杂度。\n\n# 快速开始\n\n## maven 引入\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.houbb\u003c/groupId\u003e\n    \u003cartifactId\u003eioc\u003c/artifactId\u003e\n    \u003cversion\u003e0.1.11\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## 测试准备\n\n全部测试代码，见 test 模块。\n\n- Apple.java\n\n```java\npublic class Apple {\n\n    public void color() {\n        System.out.println(\"Apple color: red. \");\n    }\n\n}\n```\n\n- apple.json\n\n类似于 xml 的配置，我们暂时使用 json 进行配置验证。\n\n```json\n[\n{\"name\":\"apple\",\"className\":\"com.github.houbb.ioc.test.service.Apple\"}\n]\n```\n\n## 执行测试\n\n- 测试\n\n```java\nBeanFactory beanFactory = new JsonApplicationContext(\"apple.json\");\nApple apple = (Apple) beanFactory.getBean(\"apple\");\napple.color();\n```\n\n- 日志\n\n```\nApple color: red.\n```\n\n# spring 基本实现流程\n\n## 说明\n\nspring-beans 一切都是围绕 bean 展开的。\n\nBeanFactory 负责对 bean 进行生命周期的相关管理，本节展示第一小节的简单实现流程。\n\n## spring 核心流程\n\nSpring IoC 主要是以下几个步骤。\n\n1. 初始化 IoC 容器。\n\n2. 读取配置文件。\n\n3. 将配置文件转换为容器识别对的数据结构（这个数据结构在Spring中叫做 BeanDefinition）\n\n4. 利用数据结构依次实例化相应的对象\n\n5. 注入对象之间的依赖关系\n\n## BeanDefinition 的抽象\n\nBeanDefinition 是 spring 对 java bean 属性的一个抽象，经过这一层抽象，配置文件可以是 xml/json/properties/yaml 等任意一种，\n甚至包括注解扫包。\n\n为 spring 的拓展带来极大的灵活性。\n\n本框架考虑到实现的简单性，初步只实现了 json 和基于注解扫包两种方式。\n\n后期如果有时间可以考虑添加 xml 的实现，其实更多是 xml 的解析工作量，核心流程已经全部实现。\n\n# 实现源码节选\n\n## BeanDefinition 相关\n\n包含了对于 java bean 的基本信息抽象。\n\n- BeanDefinition.java\n\n其默认实现为 `DefaultBeanDefinition.java`，就是对接口实现的最基本的 java POJO\n\n\u003e 参见 [DefaultBeanDefinition](https://github.com/houbb/ioc/blob/release_0.0.1/src/main/java/com/github/houbb/ioc/model/impl/DefaultBeanDefinition.java)\n\n```java\n/**\n * 对象定义属性\n * @author binbin.hou\n * @since 0.0.1\n */\npublic interface BeanDefinition {\n\n    /**\n     * 名称\n     * @return 名称\n     * @since 0.0.1\n     */\n    String getName();\n\n    /**\n     * 设置名称\n     * @param name 名称\n     * @since 0.0.1\n     */\n    void setName(final String name);\n\n    /**\n     * 类名称\n     * @return 类名称\n     */\n    String getClassName();\n\n    /**\n     * 设置类名称\n     * @param className 类名称\n     * @since 0.0.1\n     */\n    void setClassName(final String className);\n\n}\n```\n\n## BeanFactory 核心管理相关\n\n- BeanFactory.java\n\n```java\n/**\n * bean 工厂接口\n * @author binbin.hou\n * @since 0.0.1\n */\npublic interface BeanFactory {\n\n    /**\n     * 根据名称获取对应的实例信息\n     * @param beanName bean 名称\n     * @return 对象信息\n     * @since 0.0.1\n     */\n    Object getBean(final String beanName);\n\n    /**\n     * 获取指定类型的实现\n     * @param beanName 属性名称\n     * @param tClass 类型\n     * @param \u003cT\u003e 泛型\n     * @return 结果\n     * @since 0.0.1\n     */\n    \u003cT\u003e T getBean(final String beanName, final Class\u003cT\u003e tClass);\n\n}\n```\n\n- DefaultBeanFactory.java\n\n为接口最基础的实现，源码如下：\n\n```java\n/**\n * bean 工厂接口\n * @author binbin.hou\n * @since 0.0.1\n */\npublic class DefaultBeanFactory implements BeanFactory {\n\n    /**\n     * 对象信息 map\n     * @since 0.0.1\n     */\n    private Map\u003cString, BeanDefinition\u003e beanDefinitionMap = new ConcurrentHashMap\u003c\u003e();\n\n    /**\n     * 对象 map\n     * @since 0.0.1\n     */\n    private Map\u003cString, Object\u003e beanMap = new ConcurrentHashMap\u003c\u003e();\n\n    /**\n     * 注册对象定义信息\n     * @since 0.0.1\n     */\n    protected void registerBeanDefinition(final String beanName, final BeanDefinition beanDefinition) {\n        // 这里可以添加监听器\n        this.beanDefinitionMap.put(beanName, beanDefinition);\n    }\n\n    @Override\n    public Object getBean(String beanName) {\n        Object bean = beanMap.get(beanName);\n        if(ObjectUtil.isNotNull(bean)) {\n            // 这里直接返回的是单例，如果用户指定为多例，则每次都需要新建。\n            return bean;\n        }\n\n        // 获取对应配置信息\n        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);\n        if(ObjectUtil.isNull(beanDefinition)) {\n            throw new IocRuntimeException(beanName + \" not exists in bean define.\");\n        }\n\n        // 直接根据\n        Object newBean = createBean(beanDefinition);\n        // 这里可以添加对应的监听器\n        beanMap.put(beanName, newBean);\n        return newBean;\n    }\n\n    /**\n     * 根据对象定义信息创建对象\n     * @param beanDefinition 对象定义信息\n     * @return 创建的对象信息\n     * @since 0.0.1\n     */\n    private Object createBean(final BeanDefinition beanDefinition) {\n        String className = beanDefinition.getClassName();\n        Class clazz = ClassUtils.getClass(className);\n        return ClassUtils.newInstance(clazz);\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public \u003cT\u003e T getBean(String beanName, Class\u003cT\u003e tClass) {\n        Object object = getBean(beanName);\n        return (T)object;\n    }\n\n}\n```\n\n其中 ClassUtils 是基于 class 的反射工具类，详情见 [ClassUtils.java](https://github.com/houbb/ioc/blob/release_0.0.1/src/main/java/com/github/houbb/ioc/util/ClassUtils.java)\n\n## JsonApplicationContext \n\n基于 json 配置文件实现的基本实现，使用方式见开始种的例子代码。\n\n- JsonApplicationContext.java\n\n```java\n/**\n * JSON 应用上下文\n * @author binbin.hou\n * @since 0.0.1\n */\npublic class JsonApplicationContext extends DefaultBeanFactory {\n\n    /**\n     * 文件名称\n     * @since 0.0.1\n     */\n    private final String fileName;\n\n    public JsonApplicationContext(String fileName) {\n        this.fileName = fileName;\n\n        // 初始化配置\n        this.init();\n    }\n\n    /**\n     * 初始化配置相关信息\n     *\n     * \u003cpre\u003e\n     *  new TypeReference\u003cList\u003cBeanDefinition\u003e\u003e(){}\n     * \u003c/pre\u003e\n     *\n     * 读取文件：https://blog.csdn.net/feeltouch/article/details/83796764\n     * @since 0.0.1\n     */\n    private void init() {\n        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);\n        final String jsonConfig = FileUtil.getFileContent(is);\n        List\u003cDefaultBeanDefinition\u003e beanDefinitions = JsonBs.deserializeArray(jsonConfig, DefaultBeanDefinition.class);\n        if(CollectionUtil.isNotEmpty(beanDefinitions)) {\n            for (BeanDefinition beanDefinition : beanDefinitions) {\n                super.registerBeanDefinition(beanDefinition.getName(), beanDefinition);\n            }\n        }\n    }\n\n}\n``` \n\n## 小结\n\n至此，一个最基本的 spring ioc 就基本实现了。\n\n如果你想继续学习，可以分别参考以下代码分支。\n\n# 分支说明\n\n[v0.0.1-BeanFactory 基本实现](https://github.com/houbb/ioc/tree/release_0.0.1)\n\n[v0.0.2-ListBeanFactory 基本实现](https://github.com/houbb/ioc/tree/release_0.0.2)\n\n[v0.0.3-单例和延迟加载](https://github.com/houbb/ioc/tree/release_0.0.3)\n\n[v0.0.4-初始化和销毁方法](https://github.com/houbb/ioc/tree/release_0.0.4)\n\n[v0.0.5-RespCode 添加和代码优化](https://github.com/houbb/ioc/tree/release_0.0.5)\n\n[v0.0.6-构造器和 factoryMethod 新建对象](https://github.com/houbb/ioc/tree/release_0.0.6)\n\n[v0.0.7-property 属性设置](https://github.com/houbb/ioc/tree/release_0.0.7)\n\n[v0.0.8-Aware 监听器及 PostProcessor](https://github.com/houbb/ioc/tree/release_0.0.8)\n\n[v0.0.9-Parent 属性继承](https://github.com/houbb/ioc/tree/release_0.0.9)\n\n[v0.1.0-循环依赖检测](https://github.com/houbb/ioc/tree/release_0.1.0)\n\n[v0.1.1-@Configuration-java 代码配置](https://github.com/houbb/ioc/tree/release_0.1.1)\n\n[v0.1.2-@Bean-java 对象定义](https://github.com/houbb/ioc/tree/release_0.1.2)\n\n[v0.1.3-@Lazy-@Scope-java 对象属性配置](https://github.com/houbb/ioc/tree/release_0.1.3)\n\n[v0.1.4-@Import 配置导入](https://github.com/houbb/ioc/tree/release_0.1.4)\n\n[v0.1.5-@Bean 参数构造以及 @Description](https://github.com/houbb/ioc/tree/release_0.1.5)\n\n[v0.1.6-@Autowired 自动装配注解支持](https://github.com/houbb/ioc/tree/release_0.1.6)\n\n[v0.1.7-@Primary 指定优先级注解](https://github.com/houbb/ioc/tree/release_0.1.7)\n\n[v0.1.8-@Conditional 条件注解支持](https://github.com/houbb/ioc/tree/release_0.1.8)\n\n[v0.1.9-Environment 和 @Profile 实现](https://github.com/houbb/ioc/tree/release_0.1.9)\n\n[v0.1.10-Property 配置文件相关和 @Value/@PropertyResource 实现](https://github.com/houbb/ioc/tree/release_0.1.10)\n\n[v0.1.11-@ComponentScan 文件包扫描支持](https://github.com/houbb/ioc/tree/release_0.1.11)\n\n# 拓展阅读\n\n[Java IOC-00-ioc 是什么](https://houbb.github.io/2019/11/06/java-ioc-01-overview)\n\n\n# 中间件等工具开源矩阵\n\n[heaven: 收集开发中常用的工具类](https://github.com/houbb/heaven)\n\n[rpc: 基于 netty4 实现的远程调用工具](https://github.com/houbb/rpc)\n\n[mq: 简易版 mq 实现](https://github.com/houbb/mq)\n\n[ioc: 模拟简易版 spring ioc](https://github.com/houbb/ioc)\n\n[mybatis: 简易版 mybatis](https://github.com/houbb/mybatis)\n\n[cache: 渐进式 redis 缓存](https://github.com/houbb/cache)\n\n[jdbc-pool: 数据库连接池实现](https://github.com/houbb/jdbc-pool)\n\n[sandglass: 任务调度时间工具框架](https://github.com/houbb/sandglass)\n\n[sisyphus: 支持注解的重试框架](https://github.com/houbb/sisyphus)\n\n[resubmit: 防止重复提交框架，支持注解](https://github.com/houbb/resubmit)\n\n[auto-log: 日志自动输出](https://github.com/houbb/auto-log)\n\n[async: 多线程异步并行框架](https://github.com/houbb/async)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoubb%2Fioc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoubb%2Fioc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoubb%2Fioc/lists"}