死磕spring,大致还原spring的bean加载过程

总的来说:

  • 对传入的name做转化,去除&开头获得真实beanname,通过aliasMap获取是否有别名
  • 检查是否有bean的完整的引用缓存;如果没有,看singletonsCurrentlyInCreation,是不是这个bean正在创建中,看earlySingletonObjects中有没有半成品的bean(初始化但没有set属性);如果还没有,就用beanFactory获取创建中的半成品bean,放入earlySingletonObjects,同时把objectFactory移除;如果beanFactory还没有,那就是真没有了
  • 判断上一步中返回的bean,如果name不是&开头且实现factoryBean的,使用factoryBean.getObject方法获取bean,否则直接返回bean。如果上一步获取不到bean,走下一步创建bean(针对singleton)
  • beanName放到singletonsCurrentlyInCreation中,表示这个bean正在创建中;获取类定义,创建一个半成品的bean,创建ObjectFactory,放到singletonFactories中缓存,这个ObjectFactory重写了getObject方法,返回的是创建的半成品bean;其他地方拿不到缓存的完整引用bean,可以拿这个缓存ObjectFactory获取半成品的bean;populateBean设置属性,将完整的bean放到singletonObjects中缓存,移除之前的singletonsCurrentlyInCreation和ObjectFactoryMap,earlySingletonObjects。

具体步骤分析:

先看AbstractBeanFactory这个类,通过beanname获取Bean对象,后面主要分析doGetBean方法,无特殊说明都是这个类里的代码

public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }

1、解析name,如果name是以&开头的,要去除&。然后aliasMap中查看有没有别名,获取最终的beanName

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = this.transformedBeanName(name);
.......
}

2、从缓存中获取bean引用,spring只缓存singleton类型bean

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
.......
Object sharedInstance = this.getSingleton(beanName);
.........
}

DefaultSingletonBeanRegistry类:
allowEarlyReference表示是否允许由ObjectFactory获取半成品的bean。半成品bean是指初始化了bean,但是没有通过set方法设置属性。

//缓存完整的bean引用
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
//缓存baen的工厂对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
//缓存半成品的bean
private final Map<String, Object> earlySingletonObjects = new HashMap(16);
//表示beanName对应的bean正在创建中
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap(16));
public Object getSingleton(String beanName) {
        return this.getSingleton(beanName, true);
    }
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if(singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            Map var4 = this.singletonObjects;
            synchronized(this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if(singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if(singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject != NULL_OBJECT?singletonObject:null;
    }

步骤说明:
2.1、先从singletonObjects获取完整的bean引用
2.2、获取不到,判断用isSingletonCurrentlyInCreation判断该bean是否在创建中,从earlySingletonObjects中尝试获取,如果获取不到,尝试获取ObjectFactory,使用ObjectFactory获取半成品bean,并放入earlySingletonObjects中。这个地方为什么ObjectFactory获取的是半成品而不是完整的bean呢,因为后面重写了getObject方法,导致只能获取半成品。

3、对不为null的bean做处理。

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
.......
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
.........
}

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
        if(BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
        } else if(beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
            Object object = null;
            if(mbd == null) {
                object = this.getCachedObjectForFactoryBean(beanName);
            }

            if(object == null) {
                FactoryBean<?> factory = (FactoryBean)beanInstance;
                if(mbd == null && this.containsBeanDefinition(beanName)) {
                    mbd = this.getMergedLocalBeanDefinition(beanName);
                }

                boolean synthetic = mbd != null && mbd.isSynthetic();
                object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
            }

            return object;
        } else {
            return beanInstance;
        }
    }

如果这个beanInstance是实现了FactoryBean接口,且原始的name不是以&开头的,返回的对象是object是beanInstance.getObject方法返回的对象,这个也是有缓存的,先尝试从缓存中获取。
其他情况就直接返回beanInstance。
此处可以了解下FactoryBean的用法,关于ApplicationContext.getBean(beanName),beanName是否加&的区别。

4、对bean==null的处理,重头戏!
这个地方获取bean的类定义,然后获取类的构造器的依赖bean,如果这个地方有构造器循环依赖,就报错了。

final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if(dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if(this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }

                        this.registerDependentBean(dep, beanName);
                        this.getBean(dep);
                    }
                }

5、判断这个bean是否是singleton的,如果不是singleton的,创建bean,然后设置属性就完了。重点还是singleton模式的。以下只讨论singleton模式

if(mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });
                    //6、最后呢也是如同步骤3一样的细节小处理
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

5.1先看getSingleton方法,这里创建objectFactory,重写方法。
DefaultSingletonBeanRegistry类:重点是如下方法

//将beanName放入isSingletonCurrentlyInCreation。
this.beforeSingletonCreation(beanName);
...........
//创建bean,之前重写的getObject()方法
singletonObject = singletonFactory.getObject();
...........
//将beanName从isSingletonCurrentlyInCreation中移除
this.afterSingletonCreation(beanName);
...........
//将完整的bean引用放入singletonObjects,移除earlySingletonObjects,singletonFactories中引用。
this.addSingleton(beanName, singletonObject);

5.2 初始化bean,set属性
AbstractAutowireCapableBeanFactory类:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
...........
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if(earlySingletonExposure) {
            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
                public Object getObject() throws BeansException {
                    return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }
        Object exposedObject = bean;

        try {
        //populate方法就是属性注入,具体可以参考链接:http://www.imooc.com/article/19449
            this.populateBean(beanName, mbd, instanceWrapper);
            if(exposedObject != null) {
                exposedObject = this.initializeBean(beanName, exposedObject, mbd);
            }
        } catch (Throwable var18) {
            if(var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }
 ........... 

创建一个半成品的bean,以及一个ObjectFactory,重写getObject方法,返回这个半成品的bean,这就是前面步骤2。
把这个objectFactory放到singletonFactories中。

if(earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if(earlySingletonReference != null) {
                if(exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if(!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if(!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }

                    if(!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

上面这段代码就是判断创建的bean的引用和earlySingletonObjects中的引用是否一样,如果不一样,判断这个bean是否被其他bean依赖,如果没有依赖就删除所有引用,重新替换,如果有依赖的话就报错了。

循环依赖的不同情况
1、构造器循环依赖,如步骤4所示,直接失败了。
2、singleton模式的,set循环依赖,可以解决。A依赖B,B依赖C,C依赖A,那么在set属性的时候会一直循环创建bean,直到C拿到A半成品引用。特殊在bean的创建是先初始化,然后set属性。
3、其他模式的,set循环依赖,不可以解决。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值