spring 核心与源码解析(1):IoC之BeanFactory

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的创建过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值