今天工作顺利完成后,暂时没有布置新的任务,于是对spring的源码进行学习;
我就先从最重要的IOC学起吧。
先说一说为什么要使用Inversion of Control,因为在实际开发工作中,类和类之间的关系是错综复杂的,如果在每个类中都
通过new Object();这样的方式来获得需要的实例,那么程序的耦合程度就非常高。
比如说,我的车本来是使用汽油的,现在我要使用电了,那么我汽车的里面很多配件都要更换,我要打开各个零件一个个去更换;
但是我有一个IOC容器就不同了,我汽车的所有零件之间都由IOC容器来联系,我只需要告诉IOC容器,我零件要换成什么样的(通过xml文件),
那么IOC容器就会自动去帮我根据xml文件换好来,我完全不用管。
翻译成程序来讲:
使用IOC比new的好处在于,当我面对接口编程时候,具体实现类改变了,我不需要直接进到程序里面去一个又一个得手动修改,我只需要修改我的配置文件,
IOC容器就会自动通过反射技术,去实现了;
不要小看这一点,当你的业务十分复杂,类与类之间的关系也非常复杂的时候,你点进程序,一个又一个的修改,你一定会烦死的,而且容易出错,这也是为什么我们经常把一些工具类抽出来,方便重用的原因。
所谓IOC,其实就是为了方便重用,解除耦合。
理解的作用之后,我们再来看看实现原理吧!
首先,在spring中定义了最基本的IOC容器接口,Beanfactoy;
public interface BeanFactory(){
// 里面定义了7种方法,不一一列举
};
Spring提供了一些BeanFactory的基本实现,所以我们不用一一去实现,包括XmlBeanFactory等;
然而最常用的是实现类ApplicationContext;
而ClassPathXmlApplicationContext则是其子类;
首先ApplicationContext这个类有一个HashMap属性;
在带参数的构造方法中,会读取xml文件中的配置,bean的id为key,然后通过反射技术,读取bean的class,生成一个bean的实例,作为value;
最后存入HashMap<id,Object>中;
还提供了一个方法:getBean(String alias);就可以得到该实例;
以上是简单的bean的创建方法,但其实spring内部的实现机制是很复杂的,大量使用反射和内省,这里不一一剖析。
总之,Spring在其容器初始化时候,就动态拥有了所有的类的数据,放在Map中,以供调用;
值得注意的是:bean的实例生成,是我们调用getBean方法时候才生成,并不是一早就实例化的,当然,你也可以通过lazy-init属性配置。
如果想更加了解spring IOC内部实现机制,请阅读源码!