您的位置:首页 > 编程语言 > Java开发

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来实现的。

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的创建过程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring 源码 ioc