自己动手写Spring-IOC1

简单IOC1

IoC容器,也就是BeanFactory,存在的意义就是将创建对象与使用对象的业务代码解耦,让业务开发人员无需关注底层对象

(Bean)的构建和声明周期的管理,专注于业务开发。

简单IoC容器非常原始和简单,一个部件来对应Bean内存的映像;一个XML Reader负责从外部XML文件中读取Bean的配置;

一个反射部件,负责加载Bean Class并且创建这个实例;创建好实例后,用一个Map来保存Bean的实例;提供一个getBean方法供外部使用。

ioc-1.png
  1. 构建BeanDefinition
public class BeanDefinition {
    private String id;
    private String className;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public BeanDefinition(String id, String className) {
        this.id = id;
        this.className = className;
    }
}
  1. 定义BeanFactory
    此接口拥有2个方法
    1)获取一个Bean getBean()
  1. 注册一个BeanDefinition registerBeanDefinition
public interface BeanFactory {
    Object getBean(String beanName) throws NoSuchBeanDefinitionException;
    void registerBeanDefinition(BeanDefinition bd);
}
  1. 定义Resource
    把外部配置信息都当成Resource(资源)来进行抽象
    public interface Resource extends Iterator<Object> {
    }

  2. 定义ClassPathXmlResource
    目前数据来源都比较单一,读取的都是XML文件配置

public class ClassPathXmlResource implements Resource {
    Document document;
    Element rootElement;
    Iterator<Element> elementIterator;

    public ClassPathXmlResource(String fileName) {
        SAXReader saxReader = new SAXReader();
        URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
        try {
            this.document = saxReader.read(xmlPath);
            this.rootElement = document.getRootElement();
            this.elementIterator = this.rootElement.elementIterator();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean hasNext() {
        return this.elementIterator.hasNext();
    }

    @Override
    public Object next() {
        return this.elementIterator.next();
    }
}
  1. 定义XmlBeanDefinitionReader
    如何把解析好的XML转换成BeanDefinition呢?就是通过XmlBeanDefinitionReader
public class XmlBeanDefinitionReader {
    BeanFactory bf;

    public XmlBeanDefinitionReader(BeanFactory bf) {
        this.bf = bf;
    }

    public void loadBeanDefinition(Resource res) {
        while (res.hasNext()) {
            Element element = (Element) res.next();
            String beanID = element.attributeValue("id");
            String beanClassName = element.attributeValue("class");
            BeanDefinition beanDefinition = new BeanDefinition(beanID, beanClassName);
            this.bf.registerBeanDefinition(beanDefinition);
        }
    }
}
  1. BeanFactory的简单实现
public class SimpleBeanFactory implements BeanFactory {
    private List<BeanDefinition> beanDefinitions = new ArrayList<>();
    private List<String> beanNames = new ArrayList<>();
    private Map<String, Object> singletons = new HashMap<>();

    public SimpleBeanFactory() {}

    @Override
    public Object getBean(String beanName) throws NoSuchBeanDefinitionException {
        Object singleton = singletons.get(beanName);
        if (singleton == null) {
            int i = beanNames.indexOf(beanName);
            if (i == -1) {
               throw new NoSuchBeanDefinitionException();
            } else {
                BeanDefinition bd = beanDefinitions.get(i);
                try {
                    singleton = Class.forName(bd.getClassName()).newInstance();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
                singletons.put(bd.getId(), singleton);
            }
        }

        return singleton;
    }

    @Override
    public void registerBeanDefinition(BeanDefinition bd) {
        this.beanDefinitions.add(bd);
        this.beanNames.add(bd.getId());
    }
}

  1. 定义ClassPathXmlApplicationContext
public class ClassPathXmlApplicationContext implements BeanFactory {
    BeanFactory beanFactory;

    public ClassPathXmlApplicationContext(String fileName) {
        Resource res = new ClassPathXmlResource(fileName);
        BeanFactory bf = new SimpleBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
        reader.loadBeanDefinition(res);
        this.beanFactory = bf;
    }

    @Override
    public Object getBean(String beanName) throws NoSuchBeanDefinitionException {
        return this.beanFactory.getBean(beanName);
    }

    @Override
    public void registerBeanDefinition(BeanDefinition bd) {
        this.beanFactory.registerBeanDefinition(bd);
    }
}

测试:
1)定义XML配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="aservice" class="com.minis.test.AServiceImpl"></bean>

</beans>
  1. 定义接口和类
package com.minis.test;

public interface AService {
    void sayHello();
}

package com.minis.test;

public class AServiceImpl implements AService {
    @Override
    public void sayHello() {
        System.out.println("a service 1 say hello.");
    }
}
测试IOC-1.PNG

参考:极客时间 手把手带你写一个MiniSpring,以上是学习过程中的记录。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容