Spring框架中IOC设计思想剖析

学习Spring框架时对IOC设计思想的一些感悟

一句话:IOC是把自己本身创建对象和维护生命周期的权力,交给外部容器创建和维护过程的一种设计思想。


Spring和IOC的关系

这两个不是用一个东西也不是同一类东西。Spring是一个框架而IOC是一种设计思想。只不过Spring使用了IOC这个设计思想罢了。

为什么使用IOC

使用IOC之前

在使用IOC之前,若我们的Service要使用某个类时(例如TT和CC),我们要在不同的Service中分别创建一个实例,而这三个实例是不同的,这无疑会浪费不少的资源。

mark

使用IOC之后

IOC设计思想就是采用一个Container负责管理这些实例。Container采用单例设计模式,运行时会自己创建一个实例,并且只创建一个。当其他Service要使用时,Container会返回这个实例的引用,这样无论多少个Service使用该实例,堆内存中都只有一个实例。

mark

如何使用

@Component标记

首先,我们给要被管理的类(例如TT和CC)加上一个@Component注解,这代表了我们指定了这个类交给Spring进行管理。

实例化Spring容器

使用new AnnotationConfigApplicationContext()方法获得一个Spring容器,参数可以时null、工厂、注解类、包路径等等。用一个容器对象ApplicationContext context来接收这个容器。可以使用getBeanDefinitionNames()方法获取被这个Spring容器管理的对象的别名是什么。如果使用@Component(name)来指定了一个别名,那么这个对象的别名就是这个指定的别名,如果没有指定,那么别名就是这个对象的类的类名将首字母小写。例如Example类的话就是example。

原理(doScan中)

把传入的路径下面所有的类编译后的.class文件递归找出来放入一个集合对象中

在这个new AnnotationConfigApplicationContext()构造方法别调用时,他就会遍历指定的位置(例如你指定了某个包路径,就遍历这个包)。通过递归找到这个位置中所有的.class文件,并将这些类放入resources数组中。

把带有注解的类包装并放入另一个集合

使用字节码解读找到所有被注解标记的类,把带有注解的类(@Service、@Component、@Repository等)找到后包装成ScannedGenericBeanDefinition放入set<BeanDefinition>集合中。然后返回给candidates

根据BeanDefinition集合里面提供beanClassName和注解配置信息生成对应的别名。

找到这些注解的作用域

使用ScopeMetadata实例接收这些注解的作用域,作用域通过@Scope()来指定,之后通过candidates.setScope()来设置作用域。

为这些类赋予一个别名

检查这些类有没有指定没有别名,没有则使用默认方法。

把BeanDefinition对象包装成BeanDefintionHolder对象

BeanDefinitionHolder对象主要时为了保存BeanDefinition对象。

将处理好的对象存入集合中

通过BeanDefinitionRegistry接口中的registryBeanDefinition方法把传入的beanName和BeanDefinition对象交给DefaultListableBeanfactry对象中的beanDefinitionMap集合中存储

注意事项

在以上操作结束后对象还没有被实例化,只是在运行main()方法前收集记录被注解的类而已。