springIoc的原理和简单实现

首先先了解一下什么是spring

Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。
我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:Core Container 中的 Core 组件是Spring 所有组件的核心,Beans 组件和 Context 组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。
spring有两个核心IOC和AOP(本篇之谈IOC)

IOC

IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spring 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。

将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。 在实际项目中一个 Service 类可能有几百甚至上千个类作为它的底层,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。

Spring 时代我们一般通过 XML 文件来配置 Bean,后来开发人员觉得 XML 文件来配置不太好,于是 SpringBoot 注解配置就慢慢开始流行起来。
下面是IOC的初始化过程:
Spring IoC的初始化过程
https://javadoop.com/post/spring-ioc这个是IOC的源码,感兴趣的可以读一读
接下来我这里实现了一个简单的IOC,话不多说上代码:

public class SimpleIoc {
    private Map<String,Object> beanMap = new HashMap<>();

    public SimpleIoc(String path) throws Exception {
        loadBeans(path);
    }

    private void loadBeans(String path) throws Exception{
        //获取xml里的信息
        InputStream is = new FileInputStream(path);
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document parse = documentBuilder.parse(is);
        Element documentElement = parse.getDocumentElement();
        NodeList childNodes = documentElement.getChildNodes();
        //遍历xml里的bean信息
        for (int i = 0; i < childNodes.getLength(); i++){
            Node node = childNodes.item(i);
            if(node instanceof Element){
                //获取bean的id和对应的class路径
                Element ele = (Element)node;
                String id = ele.getAttribute("id");
                String className = ele.getAttribute("class");
                System.out.println(className);
                Class beanClass = null;
                //通过反射实例出他的对象
                beanClass = Class.forName(className);
                Object bean = beanClass.newInstance();
                //获取他property的信息
                NodeList property = ele.getElementsByTagName("property");
                //遍历property信息
                for(int j = 0;j<property.getLength(); j++){
                    Node item = property.item(j);
                    if(item instanceof Element) {
                        //获取属性名和要写入的属性值
                        Element pro = (Element) item;
                        String name = pro.getAttribute("name");
                        String value = pro.getAttribute("value");

                        //获取他的属性,并把它私有属性破坏
                        Field declaredField = bean.getClass().getDeclaredField(name);
                        declaredField.setAccessible(true);

                        if(value != null&&value.length()>0){
                            //写入属性值
                            declaredField.set(bean,value);
                        }else{
                            //获取ref的信息
                            String ref = pro.getAttribute("ref");
                            if(ref == null||ref.length()==0){
                                throw new IllegalArgumentException("ref config error");
                            }
                            //如果配置了这个bean就写入这个对应的属性
                            declaredField.set(bean,getBean(ref));
                        }
                        //存入map中
                        registerBean(id,bean);
                    }

                }
            }
        }
    }

    public Object getBean(String name){
        Object bean = beanMap.get(name);
        if(bean == null){
            throw new IllegalArgumentException("没有这个bean的名字");
        }
        return bean;
    }

    private void registerBean(String id,Object bean){
        beanMap.put(id,bean);
    }

1.加载 xml 配置文件,遍历其中的标签
2.获取标签中的 id 和 class 属性,加载 class 属性对应的类,并创建 bean
3.遍历标签中的标签,获取属性值,并将属性值填充到 bean 中
4.将 bean 注册到 bean 容器中
只需要简单的四部就可以实现一个简单的IOC,主要还是通过反射区实现这个IOC的容器。
最后附赠一张bean的生命周期图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值