Spring源码解析之三 ------ bean的初始化(IOC的第二步)

来源:互联网 发布:备考六级英语听力软件 编辑:程序博客网 时间:2024/06/06 01:49


在前两篇博客里,讲了spring对于自定义标签和默认标签的初始化过程。对于bean标签的解析注册,这只是IOC的第一步,而我们知道,我们经常用的bean默认是单例的,而且是spring为我们提供好的。这就涉及到IOC的第二步,为bean生成实例。

如果对spring bean的解析注册不熟悉的,可以参照 spring源码解析之一  和 spring源码解析之二

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}



前两篇对于bean标签的解析注册,我们都是从容器初始化的refresh方法中的obtainFreshBeanFactory()进去的

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

这个方法执行完毕后,返回beanFactory,我们可以看一下banFactory中存放的东西。(工程代码是 上节的自定义标签的那个工程)。

如下,在beanFactory中我们可以看到BeanDefinitionMap中,已经存放了beanName和BeanDefinition的对应信息,但是还没有实例化对象出来。


由于我们的配置的bean默认是单例的,而且lazy-init属性没有设置,而这个属性默认为false。非懒加载的单例的bean,进入 最后的 finishBeanFactoryInitialization(beanFactory)进行实例化。

直接进入这个方法,下面的代码是进入后,finishBeanFactoryInitialization的处理流程。getBean(weaverAwareName),用于加载spring bean时,织入第三方模块,如AspectJ。这个在讲AOP的时候,会用到。在现在这个工程下,获取到的weaverAwaeName是null。

我们需要进入最后一个preInstantiateSingletons()方法。从它的注释也能看出,它是加载non-lazy-init的singletons。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.beanFactory.preInstantiateSingletons();}

进入到preInstanttiateSingleton()方法后,会在最后的else里调用getBean(beanName)方法,然后又调用doGetBean()方法。所以我们进入doGetBean()方法。

这个方法里的代码很多,只取了开头的几句代码。

    protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {        final String beanName = this.transformedBeanName(name);        Object sharedInstance = this.getSingleton(beanName);        Object bean;        if(sharedInstance != null && args == null) {            if(this.logger.isDebugEnabled()) {                if(this.isSingletonCurrentlyInCreation(beanName)) {                    this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");                } else {                    this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");                }            }            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);        } else {
在上面的代码中能看出来,通过getSingleton(beanName)获取单例,这个方法会直接从beanFactory的singlentonObjects获取相应名字的bean。因为这个时候,我们的bean还没实例化,所以这个方法返回一个null。sharedInstance为空后,最后还会进入到重载的getSingleton()方法,如下。

sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {@Overridepublic 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。我们先进入createBean方法。从这个名字,也能看出这是创建bean,然后返回包含这个创建的bean的Factory。所以我们先去看看怎么创建bean,然后再跟着代码返回来。进入createBean后,代码如下:

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {if (logger.isDebugEnabled()) {logger.debug("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}Object beanInstance = doCreateBean(beanName, mbdToUse, args);//进入if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}

从上面可以看出,真正的方法在doCreateBean里面,进去之后。在初始化bean的实例前,需要看他是否是单例,并移除之前创建的。由于doCreateBean这个方法里面的内容很多,所以将这个方法里的内容按照先后顺序,一部分一部分分析。

doCreate第一部分:Instantiate the bean将bean初始化。

先判断mbd是否是单例的bean,如果是那就从bean实例的缓存里,移除相同名字的bean。然后通过调用createBeanInstance()创建bean的实例。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);mbd.postProcessed = true;}}
那么进入创建bean实例的方法:
instanceWrapper = createBeanInstance(beanName, mbd, args);

进入后,在由于我们定义的bean非常简单,没有注入属性,所以一直在最后调用了简单的instantiateBean()方法。

instantiateBean(beanName, mbd);
进入之后然后调用如下的方法:

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
进入之后,先获取bean的class,然后通过class获取构造方法,然后调用工具类BeanUtils进行初始化。进入这个方法。
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.if (bd.getMethodOverrides().isEmpty()) {Constructor<?> constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {final Class<?> clazz = bd.getBeanClass();if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {@Overridepublic Constructor<?> run() throws Exception {return clazz.getDeclaredConstructor((Class[]) null);}});}else {constructorToUse =clazz.getDeclaredConstructor((Class[]) null);}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Exception ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}return BeanUtils.instantiateClass(constructorToUse);}else {// Must generate CGLIB subclass.return instantiateWithMethodInjection(bd, beanName, owner);}}
进入BeanUtils.instantiate()之后,就是最终获取实例的方法了。下面就是这个获取实例的全部代码,可以看到它是通过构造方法的newInstance()进行实例化。

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {Assert.notNull(ctor, "Constructor must not be null");try {ReflectionUtils.makeAccessible(ctor);return ctor.newInstance(args);}catch (InstantiationException ex) {throw new BeanInstantiationException(ctor.getDeclaringClass(),"Is it an abstract class?", ex);}catch (IllegalAccessException ex) {throw new BeanInstantiationException(ctor.getDeclaringClass(),"Is the constructor accessible?", ex);}catch (IllegalArgumentException ex) {throw new BeanInstantiationException(ctor.getDeclaringClass(),"Illegal arguments for constructor", ex);}catch (InvocationTargetException ex) {throw new BeanInstantiationException(ctor.getDeclaringClass(),"Constructor threw exception", ex.getTargetException());}}

实例化之后,代码就开始返回。那么就跟着返回到doCreateBean()的方法这里。那么doCreateBean的第一部分就说完了,那么接下来继续说这个方法的第二部分。

doCreateBean方法的第二部分:解决循环引用。

这一部分主要讲循环引用的问题。这里只是说个介绍,毕竟本文的主线是bean的实例化,上面的方法已经将bean实例化出来了。这里就是做个循环引用的简单介绍,后期会单独再写一篇博客讲。讲完循环引用,然后就是讲下面源码里面的addSingletonFactory()方法。

// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.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>() {@Overridepublic Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);}});}


通过addSingletonFactory()方法,将已经注册的单例bean放在LinkedHashSet 类型的 registeredSingletons里。

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(singletonFactory, "Singleton factory must not be null");synchronized (this.singletonObjects) {if (!this.singletonObjects.containsKey(beanName)) {this.singletonFactories.put(beanName, singletonFactory);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}}

可以看到这个方法里,将这个bean加到相关的singletonFactories里和registeredSingletons里。

如下图:存放bean和实例化对象的map:singletonObjects仍然没有实例化的bean,因为在之前实例化出来后,我们还有往map中存放。然通过刚刚的register方法,registeredSingletons这个集合里,已经存放了beanName.


doCreateBean方法的第三部分:初始化bean。

上面是将bean进行了实例化,这里是将实例化的bean进行初始化。

// Initialize the bean instance.Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {exposedObject = initializeBean(beanName, exposedObject, mbd);}}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!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.");}}}}



doCreateBean方法的第四部分:register bean as disposablebean。


protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {if (mbd.isSingleton()) {// Register a DisposableBean implementation that performs all destruction// work for the given bean: DestructionAwareBeanPostProcessors,// DisposableBean interface, custom destroy method.registerDisposableBean(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));}else {// A bean with a custom scope...Scope scope = this.scopes.get(mbd.getScope());if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");}scope.registerDestructionCallback(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));}}}

做完以上的四部,doCreateBean方法就执行完毕了,返回的是我们创建的bean实例。

一直返回到

DefaultSingletonBeanRegistry类里面的
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法。


我们知道,我们的bean已经实例化,并将这个实例化的对象返回,但是还没有存map里。这个时候,返回到getSingleton()方法时候,继续往下执行,就来到下面这个方法:addSingleton()方法。在这个方法里,传入beanName和刚刚实例化出来的对象singletonObject,
if (newSingleton) {addSingleton(beanName, singletonObject);}

进入这个存入map的方法,下面这个就是。这个应该属于一看就懂的,就不解释了。

protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}

到此,实例化的bean就被放在了map类型的singletonObjects中,然后程序就开始返回。


整个流程基本就是这样,欢迎批评指正!





阅读全文
0 0
原创粉丝点击