springIOC源码解析(三)

上回讲到如何通过getBean方法来获取bean,这里感觉流程比较复杂,不知道以我的水平是否能讲清楚,如果有不清楚的地方欢迎讨论

Engine engine = (Engine)beanFactory.getBean("engine");

OK,不多废话追寻源码,这时候会遇到第一个问题XmlBeanFactory中没有getBean(String str)方法,经过查找在其父类AbstractBeanFactory中,

这里有两层逻辑,主要逻辑是首先检查bean是否初始化过,如果是则从以后的信息中获取;如果不是则从bean注册的信息中找到bean 对应的 BeanDefinition,然后创建新的bean

下面我先分析一下普通bean的初始化

protected  T doGetBean(
            final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;

        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            ......
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            ......
            if (!typeCheckOnly) {
                //标记一下这个bean被创建过
                markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                ......
                //查看这个bean是否跟其他bean有依赖关系
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        ......
                        //注册依赖bean
                        registerDependentBean(dependsOnBean, beanName);
                        getBean(dependsOnBean);
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                            //创建bean实例
                                return createBean(beanName, mbd, args);
                            }
                            ......
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
        //下面是创建prototype的过程,暂时略过不表
        ......
        return (T) bean;
    }

咱们重点来看一下spring是如何穿件单例bean的,也就是createBean(beanName, mbd, args)方法,该方法在AbstractAutowireCapableBeanFactory中实现,在该类中关键的地方是

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

明显能看到,这里就是创建实例的地方,咱们接着进去看看
springIOC源码解析(三)_第1张图片
这里先看我标注的这行,这个方法是创建一个bean实例并返回一个BeanWrapper对象,那BeanWrapper又是什么呢?接着往下看

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        .....
        return instantiateBean(beanName, mbd);
    }

springIOC源码解析(三)_第2张图片
这里能看到BeanWrapper其实是对bean的一个包装,看BeanWrapper的代码的话会发现里面包含bean的各种信息.
注意:BeanWrapper这个类很重要,bean初始化之后,对bean属性的编辑(即对属性赋值)都是通过BeanWrapper完成的
咱们接着看实例化bean的过程
springIOC源码解析(三)_第3张图片
这里主要有三部操作,首先获取class信息,然后通过class信息获取构造器,最后通过构造器创建bean实例
注意:看通过class获取构造器这里,就是这里要求bean必须要有无参构造函数

OK,到这里一个简单的spring管理bean的流程就走完了,现在咱们再来总结一下spring管理的流程
1、读取配置文件信息
2、解析配置文件信息,并把bean节点信息(包括bean的关联关系)保存在BeanDefinition中
3、把读取过的bean信息在BeanFactory中注册
4、调getBean时创建对象实例(懒加载)——通过beanName从BeanFactory中获取BeanDefinition得到bean信息,然后获取构造器创建bean实例

当然,这只是最简单的一个流程,还有很多问题是我没提到的,比如:这里是如何保证单例的?有依赖关系的Bean是如何初始化的?非延迟加载时在什么时候进行初始化的?等等,想知道这些那咱们接着一起往下探讨吧


这里应该有一个类图用来描述spring核心类的依赖关系,但我太懒.有兴趣的同学可以去网上搜一下,反正类图都是一样的

你可能感兴趣的:(个人笔记)