IOC原理

IOC的从广义范围来说,意思是控制反转,什么是控制反转呢,大家肯定都知道,以前我们要使用一个类里的方法或者属性的时候,我们先要new出这个类的对象,然后用这个对象调用里面的方法的。 这是传统方式上的使用类里的方法和属性,但是这种方式存在很大的耦合性。为了降低耦合性,Spring出了IOC控制反转,它的含义是指,Spring帮助我们来创建对象就是我们所说的bean,并且管理bean对象,当我们需要用的时候,需要Spring提供给我们创建好的bean对象。 这样就从之前我们的主动创建对象变为了,由Spring来控制创建对象,来给我们使用,也就是控制反转的意思。

对于IOC它主要设计了两个接口用来表示容器

  • 一个是BeanFactory(低级容器)
  • 一个是ApplicationContext(高级容器)

BeanFactory它是IOC容器的顶层的接口,对于BeanFactory这个容器来说,它相当一个HashMap,BeanName作为key,value就是这个bean的实例化对象,通常提供注册(put)和获取(get)两个功能。 这个实现主要是使用的工厂模式+反射技术,来进行对Bean的实例化,然后把这个实例化对象存到HashMap中,下面通过一个简单的例子来展现下BeanFactory是如何使用工厂模式+反射技术创建对象

创建一个接口类

public interface Shape {
    public void draw();
}

实现这个接口类

public class Circle implements Shape {
    public void draw(){
        System.out.println("画圆形");
    }
}
public class Square implements Shape {
    public void draw(){
       System.out.println("画方形");
    }
}

创建一个工厂类

public class ReflectFactory {
    public Shape getInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Shape shape =null;
        shape =(Shape)Class.forName(className).newInstance();
        return shape;
    }
}

创建一个Client类来进行测试

public class Client {
   public static void main(String[] args){
       ShapeFactory shapeFactory = new ShapeFactory();
       Shape shape= shapeFactory.getInstance("Circle");
       shape.draw();
   }
}

输出的是

画圆形

这个简单的小例子就是BeanFactory中通过工厂模式和反射创建对象的一个简单原理,当然BeanFactory的源码要比这个复杂的多。这里就是为了方便大家理解。

而对于ApplicationContext来说,它继承了BeanFactory这个接口,并且丰富了更多了功能在里面,这其中包括回调一些方法。这其中主要的就是有个refresh()方法,这个方法主要是刷新整个容器,即重新加载或者刷新所有的bean。

接下来给大家看下refresh()方法的源码。

1   public void refresh() throws BeansException, IllegalStateException {
 2        Object var1 = this.startupShutdownMonitor;
 3        //首先是synchronized加锁,加这个锁的原因是,避免如果你先调一次refresh()然后这次还没处理完又调一次,就会乱套了
 4        synchronized(this.startupShutdownMonitor) {
 5         //这个方法是做准备工作的,记录容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
 6            this.prepareRefresh();
 7            //这一步是把配置文件解析成一个个Bean,并且注册到BeanFactory中,注意这里只是注册进去,并没有初始化
 8            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
 9            //设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean,这里都是spring里面的特殊处理
10            this.prepareBeanFactory(beanFactory);
11
12            try {
13                //具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类,来完成一些其他的操作
14                this.postProcessBeanFactory(beanFactory);
15                //这个方法是调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory)
16                this.invokeBeanFactoryPostProcessors(beanFactory);
17                //这个方法注册 BeanPostProcessor 的实现类
18                this.registerBeanPostProcessors(beanFactory);
19                //这方法是初始化当前 ApplicationContext 的 MessageSource,国际化处理
20                this.initMessageSource();
21                //这个方法初始化当前 ApplicationContext 的事件广播器
22                this.initApplicationEventMulticaster();
23                //这个方法初始化一些特殊的 Bean(在初始化 singleton beans 之前)
24                this.onRefresh();
25                //这个方法注册事件监听器,监听器需要实现 ApplicationListener 接口
26                this.registerListeners();
27
28                //初始化所有的 singleton beans(单例bean),懒加载(non-lazy-init)的除外
29                this.finishBeanFactoryInitialization(beanFactory);
30                //方法是最后一步,广播事件
31                this.finishRefresh();
32            } catch (BeansException var9) {
33                if(this.logger.isWarnEnabled()) {
34                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
35                }
36                //调用销毁bean的方法
37                this.destroyBeans();
38                this.cancelRefresh(var9);
39                throw var9;
40            } finally {
41                this.resetCommonCaches();
42            }
43
44        }
45    }

以上就是ApplicationContext中的refresh()这个方法所做的事,里面需要看的重点的方法是ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();和this.finishBeanFactoryInitialization(beanFactory);这两个方法,大家有兴趣可以看下里面的源码,这里面包含了bean的一个生命周期。

对上面的两大块分析完成后,那么对于IOC容器的启动过程是什么样呢,说的更直白就是ClassPathXmlApplicationContext这个类启动的时候做了啥?

简单的理解,首先访问的是“高级容器”refresh方法,这个方法是使用低级容器加载所有的BeanDefinition和properties到IOC的容器中,低级容器加载成功后,高级容器开始开始处理一些回调功能。例如Bean后置处理器,回调setBeanFactory方法,和注册监听、发布事件、实例化单例Bean。

IOC做的事其实就是,低级容器(BeanFactory)加载配置文件,解析成BeanDefinition,然后放到一个map里,BeanName作为key ,这个Bean实例化的对象作为value, 使用的时候调用getBean方法,完成依赖注入。

高级容器 (ApplicationContext),它包含了低级容器的功能,当他执行 refresh 模板方法的时候,将刷新整个容器的 Bean。同时其作为高级容器,包含了太多的功能。他支持不同信息源头,支持 BeanFactory 工具类,支持层级容器,支持访问文件资源,支持事件发布通知,支持接口回调等等。