spring 核心与源码解析(1):IoC之BeanFactory
2017-12-11 10:11
716 查看
Spring两个最重要的特性之一——控制反转(Inversion of Control)。
不仅是Spring,几乎任何web框架都实现了IoC,这一特性的最大便利就是不需要手动的创建单例对象。
比如一个web应用中包含controller,service,dao等层级,我们需要实例化某个Controller类,那么就可以通过IoC,设置好该Controller的属性后,将具体的实例化工作交给Spring框架。
在java web中,Controller,Service,Dao等完成具体请求的类都被称为JavaBean,可以想象控制反转的实现极大可能采用了工厂模式,实际上IoC的内部就是通过BeanFactory来实现的。
如下:
如上为使用注解实现一个bean的IoC,其所需要的信息在配置文件application.properies中:
BeanFactory的具体实现如下:
通过反射获取Person的构造方法和setter方法,读取配置文件(以前的配置文件是xml,而现在是键值对),如果是通过xml来实现的IoC,那么就能直接将值和属性名关联起来(因为在xml中会显示声明属性名),如果是使用注解,那么BeanFactory就还需要通过解析bean的注解才能将值映射到属性上。
以上就是BeanFactory的实现原理了,其实hibernate等通过反向工程生成数据库表的原理与此类似,都是通过注解实现的。
下面开始简单阅览下BeanFactory的系列接口和实现类。
BeanFactory
可以看出BeanFactory 接口提供了最基本的获取bean的方法。
以上只是接口,具体的实现过程如何?
不用说,DefaultListableBeanFactory也是通过层层实现接口,继承抽象类来实现了最下层的一个可用的BeanFactory。
其属性源码定义如下:
除了列出DefaultListableBeanFactory的beanDefinitionMap和beanDefinitionNames 属性,上述代码还列出了DefaultSingletonBeanRegistry的singletonObjects的属性定义。
如此一来,扫描部分的任务就结束了。但此时bean还未被生成,只是通过读取bean获取了bean的定义类(BeanDefinition)。下面代码展示了DefaultListableBeanFactory是如何将BeanDefinition注入到beanDefinitionMap中的:
以上是DefaultListableBeanFactory在完成生成bean前的准备工作。
具体的方法就是每次从beanDefinitionNames获取一个beanName,然后调用getBean方法(注意getBean是最底层的BeanFactory的方法),其具体实现是在AbstractBeanFactory中完成的(上图的第三层)。
OK,说道AbstractBeanFactory,该类是除开DefaultListableBeanFactory最重要的一个BeanFactory类了,因为该抽象类实现了创建bean的方法。
具体实现是在该类的doGetBean方法中。
该方法内部实际使用过取得beanName的BeanDefinition然后在交由AbstractAutowireCapableBeanFactory的createBean方法实现的,具体细节就不去理了。不过只提一点:
具体生成bean的方法有很多,比如反射,通过构造函数,setter方法,甚至直接获取属性后设置值(即绕过构造函数和setter方法),另外一类方法就是使用CGLIB来构建bean。
创建完毕后,就将该bean放在DefaultSingletonBeanRegistry的singletonObjects属性中。
以上过程就完成了整个bean的创建过程。
不仅是Spring,几乎任何web框架都实现了IoC,这一特性的最大便利就是不需要手动的创建单例对象。
比如一个web应用中包含controller,service,dao等层级,我们需要实例化某个Controller类,那么就可以通过IoC,设置好该Controller的属性后,将具体的实例化工作交给Spring框架。
在java web中,Controller,Service,Dao等完成具体请求的类都被称为JavaBean,可以想象控制反转的实现极大可能采用了工厂模式,实际上IoC的内部就是通过BeanFactory来实现的。
BeanFactory
不要被IoC所迷惑,具体的控制反转实现仍然使用常见的技术,即反射。在引入注解的IoC实现后,多了注解而已。如下:
@Component(value = "person") public class Person { @Value("${spring.bean.person.name}") private String name; @Value("${spring.bean.person.age}") private int age; ... }
如上为使用注解实现一个bean的IoC,其所需要的信息在配置文件application.properies中:
spring.bean.person.name = "Test" spring.bean.person.age = 12
BeanFactory的具体实现如下:
通过反射获取Person的构造方法和setter方法,读取配置文件(以前的配置文件是xml,而现在是键值对),如果是通过xml来实现的IoC,那么就能直接将值和属性名关联起来(因为在xml中会显示声明属性名),如果是使用注解,那么BeanFactory就还需要通过解析bean的注解才能将值映射到属性上。
以上就是BeanFactory的实现原理了,其实hibernate等通过反向工程生成数据库表的原理与此类似,都是通过注解实现的。
下面开始简单阅览下BeanFactory的系列接口和实现类。
BeanFactory
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String var1) throws BeansException; <T> T getBean(String var1, Class<T> var2) throws BeansException; boolean containsBean(String var1); boolean isSingleton(String var1); boolean isPrototype(String var1)
可以看出BeanFactory 接口提供了最基本的获取bean的方法。
以上只是接口,具体的实现过程如何?
DefaultListableBeanFactory
整个IoC容器中创建bean的最重要的类——DefaultListableBeanFactory。不用说,DefaultListableBeanFactory也是通过层层实现接口,继承抽象类来实现了最下层的一个可用的BeanFactory。
其属性源码定义如下:
//DefaultListableBeanFactory public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256); private volatile List<String> beanDefinitionNames = new ArrayList(256); ... } //DefaultSingletonBeanRegistry public class DefaultSingletonBeanRegistry extends...{ private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256); }
除了列出DefaultListableBeanFactory的beanDefinitionMap和beanDefinitionNames 属性,上述代码还列出了DefaultSingletonBeanRegistry的singletonObjects的属性定义。
初始化beanDefinitionMap
应用启动时,ApplicationContext首先扫描scanBasePackages定义的包(如果是xml配置,那就是读取xml配置文件,当然此时的BeanFactory就不是DefaultListableBeanFactory了而是XmlBeanFactory),然后读取包里的类,通过注解和反射的方式,生成和包中的bean对应的BeanDefinition,载入到DefaultListableBeanFactory的beanDefinitionMap中如此一来,扫描部分的任务就结束了。但此时bean还未被生成,只是通过读取bean获取了bean的定义类(BeanDefinition)。下面代码展示了DefaultListableBeanFactory是如何将BeanDefinition注入到beanDefinitionMap中的:
public class DefaultListableBeanFactory ... { /** * 该方法被ApplicationContext调用,在调用该方法前, * ApplicationContext必然先获取了所有的BeanDefinition */ public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) { ... BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName); if(oldBeanDefinition != null) { ... }else { if(this.hasBeanCreationStarted()) { Map var4 = this.beanDefinitionMap; //同步代码块,初始化 synchronized(this.beanDefinitionMap) { //将beanName,beanDefinition放入beanDefinitionMap this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if(this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { this.beanDefinitionMap.put(beanName, beanDefinition); //将beanName添加进beanDefinitionNames this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } } }
以上是DefaultListableBeanFactory在完成生成bean前的准备工作。
创建bean
DefaultListableBeanFactory中的beanDefinitionMap和beanDefinitionNames初始化完成后,通过迭代beanDefinitionNames完成创建bean的过程。具体的方法就是每次从beanDefinitionNames获取一个beanName,然后调用getBean方法(注意getBean是最底层的BeanFactory的方法),其具体实现是在AbstractBeanFactory中完成的(上图的第三层)。
OK,说道AbstractBeanFactory,该类是除开DefaultListableBeanFactory最重要的一个BeanFactory类了,因为该抽象类实现了创建bean的方法。
具体实现是在该类的doGetBean方法中。
该方法内部实际使用过取得beanName的BeanDefinition然后在交由AbstractAutowireCapableBeanFactory的createBean方法实现的,具体细节就不去理了。不过只提一点:
具体生成bean的方法有很多,比如反射,通过构造函数,setter方法,甚至直接获取属性后设置值(即绕过构造函数和setter方法),另外一类方法就是使用CGLIB来构建bean。
创建完毕后,就将该bean放在DefaultSingletonBeanRegistry的singletonObjects属性中。
以上过程就完成了整个bean的创建过程。
相关文章推荐
- 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
- 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
- Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
- 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
- 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
- Spring源码学习-1.IOC-DefaultListableBeanFactory
- (精)Spring IOC核心源码学习III:bean标签和自定义标签实现原理
- spring源码解析_BeanFactory
- Spring源码解析笔记9——容器的功能扩展BeanFactory的后处理(BeanFactoryPostProcessor)
- 【spring】源码解析之 DefaultListableBeanFactory 和 XmlBeanDefinitionReader
- Spring源码-IOC容器(二)-Bean的定位解析注册
- 解析Spring源码(10)---AbstractBeanFactory
- 做一个合格的程序猿之浅析Spring IoC源码(二)BeanFactory初始化
- spring 核心与源码解析(2):IoC之ApplicationContext
- Spring IoC容器之BeanFactory底层实现代码解析(一)
- spring beans源码解读之 ioc容器之始祖--DefaultListableBeanFactory
- 先码后看 spring IOC源码(beanfactory、applicationcontext、webapplicationcontext) 侵立删
- (六)Spring核心框架 - IOC的源码解析
- 【第二章:源码解析】Spring的BeanFactory的接口注解