Tiny-Spring源码阅读(一)IOC的理解

来源:互联网 发布:iphone通讯录数据恢复 编辑:程序博客网 时间:2024/05/28 01:36

Tiny-Spring作为spring一个简化版本,既包含了springIOC 与SpringAOP的主要部分,而且去除了其他不必要的成分,对于Spring的认识更加清晰,如果看Spring所有源码头大的话,可以看它。下面是我这几天对于TinySpring源码阅读的理解。特此记录。

一、什么是IOC?

IOC又叫做控制反转,过去生成代码需要手工new出来对象,使用IOC之后,可以将对象的创建交给Spring容器。这样很大程度上降低了耦合度。

二、IOC实现

(1) 对象的管理

Tiny-Spring对象的管理主要是通过BeanFactory,BeanFactory是一个接口,它只有一个方法getBean,用于对象的获取。

public interface BeanFactory {    Object getBean(String name) throws Exception;}

接下来是AbstractBeanFactory,作为IOC容器,它确定了一个容器的基本功能:
(1)将一个bean注册进容器中,bean的存储是通过哈希map实现。bean的id是键,值通过BeanDefinition存储,它包括了了对象的实例,className,Class,propertyValues。
(2)创建容器内的bean实例,它通过doCreateBean。并且AbstractBeanFactory将bean的创建分为两部分,实例化对象createBeanInstance以及加载对象的属性applyPropertyValues。并且,加载对象的属性交给子类实现,这样可以实现不同策略的加载方式。
另外,作为一个对象的属性property作为一个单独的类PropertyValue,这样更方便存储属性以及读取,而且一个对象所有的property保存在一个单独的类PropertyValues当中,而不是一个list,这样做是为了可以对propertyValue进行更多的操作,比如判重。另外需要注意:如果依赖的属性是另外一个类,那么它就是一个BeanReference,以此来区别普通属性。
然后定义了AutowireCapableBeanFactory,继承自AbstractBeanFactory,它作为一个自动装配的bean,在对象加载的时候自动完成属性的注入。这样一个基本的IOC容器就完成了。
测试代码:

        AbstractBeanFactory abstractBeanFactory=new AutowireCapableBeanFactory();        BeanDefinition beanDefinition=new BeanDefinition();        beanDefinition.setBeanClassName("us.codecraft.tinyioc.context.Luck");        abstractBeanFactory.registerBeanDefinition("luck", beanDefinition);        Luck luck= (Luck) abstractBeanFactory.getBean("luck");        luck.show();

(2)资源的加载

     接下来,就需要考虑通过加载资源的方式加载属性了。首先,先考如何获取资源,tiny-spring定义了一个Resource接口,它只声明了一个方法,用于获取资源。
 public interface Resource {    InputStream getInputStream() throws IOException; }   

然后就是具体的获取资源的方式了,tiny-spring只定义了URLResource获取资源,继承自Resource,当然也可以自己扩展。有了获取资源的方式,接下来需要考虑如何加载资源了,tiny-spring通过定义ResourceLoader类加载资源,它通过location获取资源路径,然后通过不同方式进行加载,单独这样定义一个类的目的是在有多种获取资源的方式的时候,减少了耦合度,但作者这个方法类我感觉不太妥当,getResource方法写死了。

(3)将资源载入容器中

有了加载资源的方式了,接下来的任务就是将资源加载到对象(BeanDefinition)中去了。Tiny-Spring提供了一个BeanDefinitionReader接口,以及它的抽象类AbstractBeanDefinitionReader,它的作用是获取ResourceLoader以及读取资源到beanDefinition对应的哈希map。然后是它的一个实现类XmlBeanDefinitionReader,它通过读取xml文件的方式将资源载入到哈希map中。
接下来任务就是将资源放入IOC容器中去了,这时候先使用ApplicationContext,它继承了BeanFactory,用于获取bean,然后是AbstractApplicationContext继承自ApplicationContext,它定义了加载资源方法refresh,以及加载策略onRefresh,表示在资源读取完成后立即将所有在容器中的对象实例化。同时,它还有一个抽象方法loadBeanDefinitions,表示资源载入容器中的方式。这个方法交给具体类实现,这里是ClassPathXmlApplicationContext,它的loadBeanDefinitions获取xml文件中的资源并将其放入容器中。然后就有了我们在Spring中常见的资源加载方式:

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("tinyioc-postbeanprocessor.xml");        Hello helloWorldService = (Hello) applicationContext.getBean("show");        helloWorldService.show();

三、总结

在Tiny-Spring IOC部分,用到的设计模式有,工厂模式,模板模式(定义了一个抽象类,类中一些方法交给子类来实现)。而且每一个类中的方法基本上符合单一职能原则,对于代码写的还比较差劲的人来说(比如我),真的有很大收获。代码虽然简洁,但是对于SpringIOC部分已经刻画的很详细了。

ps:渣渣一枚,如有不对请大佬指出。