Spring bean的加载过程

来源:互联网 发布:cdlinux安装软件 编辑:程序博客网 时间:2024/05/23 21:06

一、问题引入:

ctx.getBean方法是如何运作的 ?

public static void main(String[] args) {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");// 读取bean.xml中的内容
    TestBean testBean = ctx.getBean("testBean",TestBean.class);
    System.out.println(testBean.getA());
}

二、doGetBean加载概述:

 

 

 

AbstractBeanFactory.doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)

 doGetBean()

1. 首先这里会将传入的beanName进行转化。代码如下所示:

final String beanName = transformedBeanName(name):
protected String transformedBeanName(String name) {
   return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

转化有两个步骤,首先处理beanName为&XXX的格式,这里表示要取指定name的factoryBean。在这里先把&符号取消,先获取bean再处理。然后,针对bean的alias机制,这里传入的参数可能是一个bean别名,那么我们先获取这个bean的主要id,只需要根据id值取bean就可以了。

2.判断这个beanName的bean是否已经创建了【缓存获取】,代码如下:

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
 
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
 
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
protected Object getSingleton(String beanName, boolean allowEarlyReference) { 
        //检查缓存中是否存在实例 
        Object singletonObject = this.singletonObjects.get(beanName); 
        if (singletonObject == null) { 
            //如果为空,则锁定全局变量并进行处理 
            synchronized (this.singletonObjects) { 
                //如果此bean正在加载则不处理 
                singletonObject = this.earlySingletonObjects.get(beanName); 
                if (singletonObject == null && allowEarlyReference) { 
                    //当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories 
                    ObjectFactory singletonFactory = this.singletonFactories.get (beanName); 
                    if (singletonFactory != null) { 
                        //调用预先设定的getObject方法 
                        singletonObject = singletonFactory.getObject(); 
                        //记录在缓存中,earlySingletonObjects和singletonFactories互斥 
                        this.earlySingletonObjects.put(beanName, singletonObject); 
                        this.singletonFactories.remove(beanName); 
                    
                
            
        
        return (singletonObject != NULL_OBJECT ? singletonObject : null); 
    }


3.尝试从父容器中寻找,这一点和classLoader的父子加载机制相同。代码如下所示

BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    // Not found -> check parent.
    String nameToLookup = originalBeanName(name);
    if (args != null) {
        // Delegation to parent with explicit args.
        return (T) parentBeanFactory.getBean(nameToLookup, args);
    }
    else {
        // No args -> delegate to standard getBean method.
        return parentBeanFactory.getBean(nameToLookup, requiredType);
    }
}

4.获取bean定义信息

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

这里会对bean信息进行一个封装,主要是处理parent信息和scope信息。将这些信息进行一次定义融合,同时接下来对bean进行检查。

5. 处理依赖信息,这里会针对xml定义中的depends-on进行处理。如下面代码所示:

String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dependsOnBean : dependsOn) {
        if (isDependent(beanName, dependsOnBean)) {
            throw new BeanCreationException("Circular depends-on relationship between '" +
                                beanName + "' and '" + dependsOnBean + "'");
        }
        registerDependentBean(dependsOnBean, beanName);
        getBean(dependsOnBean);
    }
}

6.调用getSingleton(String beanName, ObjectFactory singletonFactory),最终会触发objectFactory的getObject方法,即调用createBean(beanName, mbd, args)方法进行bean创建。代码如下所示:

// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    @Override
    public Object getObject() throws BeansException {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
           // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
        }
    }
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

三、循环依赖

       循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环。此处不是循环调用,循环调用是方法之间的环调用。

 Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?

 

  • 构造器循环依赖:表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。

 

如在创建CircleA类时,构造器需要CircleB类,那将去创建CircleB,在创建CircleB类时又发现需要CircleC类,则又去创建CircleC,最终在创建CircleC时发现又需要CircleA;从而形成一个环,没办法创建。

 

Spring容器将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。

 

  • setter循环依赖:表示通过setter注入方式构成的循环依赖。

 

对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器注入但未完成其他步骤(如setter注入)的Bean来完成的,而且只能解决单例作用域的Bean循环依赖。

四、doCreateBean()-bean生命周期

AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])

在进入doCreateBean()之前,执行一次如下的操作:

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbd
if (bean != null) {
    return bean;
}

我的理解:主要是处理实现了InstantiationAwareBeanPostProcessor的后置处理器,相当于给我们开发者一个在bean真正创建的的机会进行代理逃逸或者对配置做一些修改。

bean真正执行的函数:doCreateBean:

1:Bean的建立:

容器寻找Bean的定义信息并将其实例化。

(1)基于FactoryBean实例化

(2)基于构造器的实例化。

  • 默认构造器或者是不带lookup或者replace配置方法时实例化使用java反射直接实现
  • 否则使用动态代理将配置特性加入bean中

插一个过程,处理循环依赖的提前曝光策略:

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }


2:属性注入:

使用依赖注入,Spring按照Bean定义信息配置Bean所有属性。

populateBean(beanName, mbd, instanceWrapper);

插一个过程:initializeBean():

后面的3-8的步骤均在此方法中调用:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }
 
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
 
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
 
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}


3:BeanNameAware的setBeanName():

如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。

4:BeanFactoryAware的setBeanFactory():

如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

5:BeanPostProcessors的ProcessBeforeInitialization()

如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。

6:initializingBean的afterPropertiesSet():

如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法

7:Bean定义文件中定义init-method:

可以在Bean定义文件中使用"init-method"属性设定方法名称例如:

如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法

8:BeanPostProcessors的ProcessaAfterInitialization()

如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法

五、Bean生命周期应用

自定义注解实现Logger

原创粉丝点击