从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类。实际IOC容器。所以这篇博客以DefaultListableBeanFactoryIOC容器为基准进行IOC原理解析。

一.两个重要接口

前面已经分析了BeanFactor,它的三个直接子类接口,接下来我们继续分析两个重要的接口,可以看到这两个接口也是集大成者。

首先是ConfigurableBeanFactor

1.ConfigurableBeanFactory

从名字可以看到,这是一个可以配置的接口,但是究竟在配置什么呢?

(1)接口定义

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry

可以看到继承了HierarchicalBeanFactory和SingletonBeanRegistry两个接口。

表明实现这个接口的类都是可以分层,支持单例的IOC容器。

(2)java doc

/**
* Configuration interface to be implemented by most bean factories. Provides
* facilities to configure a bean factory, in addition to the bean factory
* client methods in the {@link org.springframework.beans.factory.BeanFactory}
* interface.
*
* <p>This bean factory interface is not meant to be used in normal application
* code: Stick to {@link org.springframework.beans.factory.BeanFactory} or
* {@link org.springframework.beans.factory.ListableBeanFactory} for typical
* needs. This extended interface is just meant to allow for framework-internal
* plug'n'play and for special access to bean factory configuration methods.
*/

1.这个接口被大量实现,配置了可以配置容器的方法。

2.这个接口不是常用接口,依赖于BeanFactory和ListableBeanFactory接口,只是属于框架的一部分。

(3) 源码

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype"; /**
* Set the parent of this bean factory.
* <p>Note that the parent cannot be changed: It should only be set outside
* a constructor if it isn't available at the time of factory instantiation.
*/
//可以设置父工厂,但是值得注意的是,只能设置一次,不能改变
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException; /**
* Set the class loader to use for loading bean classes.
* Default is the thread context class loader.
* <p>Note that this class loader will only apply to bean definitions
* that do not carry a resolved bean class yet. This is the case as of
* Spring 2.0 by default: Bean definitions only carry bean class names,
* to be resolved once the factory processes the bean definition.
* @param beanClassLoader the class loader to use,
* or {@code null} to suggest the default class loader
*/
//配置ClassLoader,只是应用于Bean definition
void setBeanClassLoader(ClassLoader beanClassLoader); /**
* Return this factory's class loader for loading bean classes.
*/
ClassLoader getBeanClassLoader(); void setTempClassLoader(ClassLoader tempClassLoader);
ClassLoader getTempClassLoader(); /**
* Set whether to cache bean metadata such as given bean definitions
* (in merged fashion) and resolved bean classes. Default is on.
* <p>Turn this flag off to enable hot-refreshing of bean definition objects
* and in particular bean classes. If this flag is off, any creation of a bean
* instance will re-query the bean class loader for newly resolved classes.
*/
/// 设置、是否缓存元数据,如果false,那么每次请求实例,都会从类加载器重新加载(热加载),这里还不太懂
void setCacheBeanMetadata(boolean cacheBeanMetadata); /**
* Return whether to cache bean metadata such as given bean definitions
* (in merged fashion) and resolved bean classes.
*/
boolean isCacheBeanMetadata(); //表达式支持,配置表达式支持器
void setBeanExpressionResolver(BeanExpressionResolver resolver); BeanExpressionResolver getBeanExpressionResolver(); //配置conversionService??转换服务?
void setConversionService(ConversionService conversionService);
ConversionService getConversionService(); //配置属性编辑器
void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass); void copyRegisteredEditorsTo(PropertyEditorRegistry registry); //配置类型转换器?TypeCoverter
void setTypeConverter(TypeConverter typeConverter); TypeConverter getTypeConverter(); //字符串处理器?
void addEmbeddedValueResolver(StringValueResolver valueResolver); //处理字符串
String resolveEmbeddedValue(String value); /**
* Add a new BeanPostProcessor that will get applied to beans created
* by this factory. To be invoked during factory configuration.
* <p>Note: Post-processors submitted here will be applied in the order of
* registration; any ordering semantics expressed through implementing the
* {@link org.springframework.core.Ordered} interface will be ignored. Note
* that autodetected post-processors (e.g. as beans in an ApplicationContext)
* will always be applied after programmatically registered ones.
* @param beanPostProcessor the post-processor to register
*/
//添加后处理器
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); /**
* Return the current number of registered BeanPostProcessors, if any.
*/
int getBeanPostProcessorCount(); void registerScope(String scopeName, Scope scope); String[] getRegisteredScopeNames(); Scope getRegisteredScope(String scopeName); AccessControlContext getAccessControlContext(); void copyConfigurationFrom(ConfigurableBeanFactory otherFactory); //注册别名依赖关系
void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException; void resolveAliases(StringValueResolver valueResolver); BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; /**
* Determine whether the bean with the given name is a FactoryBean.
boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException; void setCurrentlyInCreation(String beanName, boolean inCreation); boolean isCurrentlyInCreation(String beanName); //注册依赖Bean
void registerDependentBean(String beanName, String dependentBeanName); String[] getDependentBeans(String beanName); String[] getDependenciesForBean(String beanName); void destroyBean(String beanName, Object beanInstance); void destroyScopedBean(String beanName); void destroySingletons(); }

好吧,好一个可配置,吓尿了有点。总的来说,还是在配置一些IOC容器,没有超出IOC容器。

总结一下,我现阶段能看懂的部分:

1.首先是两个作用领域对象,判断是否为singleton,单例还是Prototype,原型。应用于方法registerScope。这两个有啥区别??

1。 当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean。

2。 prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。)

参考内容

2.第二个就是setParentBeanFactory,这个方法后面会被大量使用。对应于getParentBeanFactory。

3.还有一些处理器的配置,重点关注后处理器配置,addBeanPostProcessor以及ClassLoader配置,setBeanClassLoader。

2.ConfigurableListableBeanFactory

(1)接口定义

public interface ConfigurableListableBeanFactory
        extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory

从这里就可以看出,ConfigurableListableBeanFactory继承了上面提到的所有接口,所以它是最后的大Boss。真正的集大成者IOC容器接口,而不再是小儿科了。

(2)java doc

/**
* Configuration interface to be implemented by most listable bean factories.
* In addition to {@link ConfigurableBeanFactory}, it provides facilities to
* analyze and modify bean definitions, and to pre-instantiate singletons.
*
* <p>This subinterface of {@link org.springframework.beans.factory.BeanFactory}
* is not meant to be used in normal application code: Stick to
* {@link org.springframework.beans.factory.BeanFactory} or
* {@link org.springframework.beans.factory.ListableBeanFactory} for typical
* use cases. This interface is just meant to allow for framework-internal
* plug'n'play even when needing access to bean factory configuration methods.
*/

1.对ConfigurableBeanFactory接口的扩充,提供了分析和调整Bean definition的方法。

2.依然不是常用接口?什么叫常用接口呢。并不是在实际编程应用过程中常使用的接口代码。这里的意思可能是我们向上转型建立BeanFactor时,没必要指定一个实例为该接口。可以是BeanFactory或者是ListableBeanFactory。

(3)源码

public interface ConfigurableListableBeanFactory
extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory { /**
* Ignore the given dependency type for autowiring:
* for example, String. Default is none.
* @param type the dependency type to ignore
*/
//忽略自动装配的依赖类型
void ignoreDependencyType(Class<?> type); /**
* Ignore the given dependency interface for autowiring.
* <p>This will typically be used by application contexts to register
* dependencies that are resolved in other ways, like BeanFactory through
* BeanFactoryAware or ApplicationContext through ApplicationContextAware.
* <p>By default, only the BeanFactoryAware interface is ignored.
* For further types to ignore, invoke this method for each type.
* @param ifc the dependency interface to ignore
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.context.ApplicationContextAware
*/
//忽略自动装配的依赖接口
void ignoreDependencyInterface(Class<?> ifc); /**
* Register a special dependency type with corresponding autowired value.
* <p>This is intended for factory/context references that are supposed
* to be autowirable but are not defined as beans in the factory:
* e.g. a dependency of type ApplicationContext resolved to the
* ApplicationContext instance that the bean is living in.
* <p>Note: There are no such default types registered in a plain BeanFactory,
* not even for the BeanFactory interface itself.
*/
//注册一个特殊的依赖类型
//用来解决FactorBean引用来注册在容器中
void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue); /**
* Determine whether the specified bean qualifies as an autowire candidate,
* to be injected into other beans which declare a dependency of matching type.
* <p>This method checks ancestor factories as well.
* @param beanName the name of the bean to check
* @param descriptor the descriptor of the dependency to resolve
* @return whether the bean should be considered as autowire candidate
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
*/
//决定这个Bean是否应该被其他Bean自动装配。
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException; /**
* Return the registered BeanDefinition for the specified bean, allowing access
* to its property values and constructor argument value (which can be
* modified during bean factory post-processing).
* <p>A returned BeanDefinition object should not be a copy but the original
* definition object as registered in the factory. This means that it should
* be castable to a more specific implementation type, if necessary.
* <p><b>NOTE:</b> This method does <i>not</i> consider ancestor factories.
* It is only meant for accessing local bean definitions of this factory.
* @param beanName the name of the bean
* @return the registered BeanDefinition
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* defined in this factory
*/
//返回对应Bean的BeanDefinition
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; /**
* Return a unified view over all bean names managed by this factory.
* <p>Includes bean definition names as well as names of manually registered
* singleton instances, with bean definition names consistently coming first,
* analogous to how type/annotation specific retrieval of bean names works.
* @return the composite iterator for the bean names view
* @since 4.1.2
* @see #containsBeanDefinition
* @see #registerSingleton
* @see #getBeanNamesForType
* @see #getBeanNamesForAnnotation
*/
//返回一个Bean名称的迭代器
Iterator<String> getBeanNamesIterator(); /**
* Freeze all bean definitions, signalling that the registered bean definitions
* will not be modified or post-processed any further.
* <p>This allows the factory to aggressively cache bean definition metadata.
*/
//锁定Bean配置,不在改变
void freezeConfiguration(); /**
* Return whether this factory's bean definitions are frozen,
* i.e. are not supposed to be modified or post-processed any further.
* @return {@code true} if the factory's configuration is considered frozen
*/
boolean isConfigurationFrozen(); /**
* Ensure that all non-lazy-init singletons are instantiated, also considering
* {@link org.springframework.beans.factory.FactoryBean FactoryBeans}.
* Typically invoked at the end of factory setup, if desired.
* @throws BeansException if one of the singleton beans could not be created.
* Note: This may have left the factory with some beans already initialized!
* Call {@link #destroySingletons()} for full cleanup in this case.
* @see #destroySingletons()
*/
//初始化所有的单例。
void preInstantiateSingletons() throws BeansException; }

值得注意的方法就是可以根据Bean的名称返回BeanDefinition,以及可以可以与初始化所有单例。还有就是返回Bean Name的迭代器。

二. DefaultListableBeanFactory

1. 定义

public class DefaultListableBeanFactory extends

AbstractAutowireCapableBeanFactory  implements

ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

只继承了一个抽象类,同时把集大成的接口ConfigurableListableBeanFactory给实现了,同时还有BeanDefinitionRegistry接口,从名字上看就知道是BeanDefinition的注册接口。

2.Java doc

/**
* Default implementation of the
* {@link org.springframework.beans.factory.ListableBeanFactory} and
* {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory
* based on bean definition objects.
*//一个完整的,成熟的IOC容器
* <p>Typical usage is registering all bean definitions first (possibly read
* from a bean definition file), before accessing beans. Bean definition lookup
* is therefore an inexpensive operation in a local bean definition table,
* operating on pre-built bean definition metadata objects.
*//主要作为注册Bean definition
* <p>Can be used as a standalone bean factory, or as a superclass for custom
* bean factories. Note that readers for specific bean definition formats are
* typically implemented separately rather than as bean factory subclasses:
* see for example {@link PropertiesBeanDefinitionReader} and
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
*
* <p>For an alternative implementation of the
* {@link org.springframework.beans.factory.ListableBeanFactory} interface,
* have a look at {@link StaticListableBeanFactory}, which manages existing
* bean instances rather than creating new ones based on bean definitions.
*
* @author Rod Johnson
* @author Juergen Hoeller//注意这两个作者
*/

它是真正第一个可以独立的IOC容器,而且后面的ApplicationContext据说也是依据它来建立。在访问bean前,先注册所有的definition(可能从bean definition配置文件中)。使用预先建立的bean定义元数据对象,从本地的bean definition表中查询bean definition因而将不会花费太多成本。这个类的直接子类只有XMLBeanFactory,二者的唯一区别就是后者集成了处理XML形式BeanDefinition的方法。

三.IOC容器实现原理

这次先不关注源码,先首先看看它的用法,例子参考<Spring 技术内幕>

ClassPathResource res=new ClassPathResource("beans.xml");
DefaultListableBeanFactory factory=new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
Performer performer=(Performer) factory.getBean("dancer");
performer.perform();

简单解释一下:

1.我们在beans.xml中定义了一个Bean,id为“dancer”,实现了Performer接口。参考自<Spring in action>例子.

2.利用Resource抽象实现类,来包装这个包含了BeanDefinition的定义信息。

3.创建一个BeanFactory,DefaultListableBeanFactory

4.创建一个载入BeanDefinition的读取器,通过回调配置给BeanFactory.

5. 从定义好好的Resource中,读取配置信息。由XmlBeanDefinitionReader完成解析,完成整个载入和注册Bean定义的过程。

6. 通过BeanFactory的getBean()方法,获取对应的Bean。这里涉及到了Bean的实例化以及依赖注入

其实这也是XmlBeanFactory的实现形式,可以参考其实现源码

public class XmlBeanFactory extends DefaultListableBeanFactory {

    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

    /**
* Create a new XmlBeanFactory with the given resource,
* which must be parsable using DOM.
* @param resource XML resource to load bean definitions from
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
} /**
* Create a new XmlBeanFactory with the given input stream,
* which must be parsable using DOM.
* @param resource XML resource to load bean definitions from
* @param parentBeanFactory parent bean factory
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
} }

beans.xml的定义如下所示:

简单解释一下例子,Dancer类共有三个属性,一个是danceStyle,一个是name,这两个都是String类型的,另一个是partner,是Dancer类型,所以这里采用了内部类的形式。Dancer类继承了Performer接口,实现了接口的perform方法。

*******************单步调试分析****************

1.ClassPathResource res=new ClassPathResource("beans.xml");

可见Resource 是对Resource文件的定位过程。提供了两个属性,一个是ClassLoader,另一个是path路径。是对输入流的一个包装。

2.DefaultListableBeanFactory factory=new DefaultListableBeanFactory();

接下来单步运行看一下IOC容器创建的过程。

(1) 可见DefaultListableBeanFactory,只是调用父类构造器

(2)父类是AbstractAutowireCapableBeanFactory抽象容器

额,继续上调默认构造器,同时会调用IgnoreDependencyInterface方法,查看一下这个方法,参数为Class类型。

/**
* Ignore the given dependency interface for autowiring.
* <p>This will typically be used by application contexts to register
* dependencies that are resolved in other ways, like BeanFactory through
* BeanFactoryAware or ApplicationContext through ApplicationContextAware.
* <p>By default, only the BeanFactoryAware interface is ignored.
* For further types to ignore, invoke this method for each type.
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.context.ApplicationContextAware
*/
public void ignoreDependencyInterface(Class<?> ifc) {
this.ignoredDependencyInterfaces.add(ifc);
}

这个方法主要是需要自动装配时,忽略的接口类型,ignoredDependencyInterfaces是Set类型的,private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<Class<?>>();

所以在自动装配的时候,会自动忽略BeanNameAware.class,BeanFactoryAware.class,BeanClassLoaderAware.class接口类型的类。

(3)父类构造器AbstractBeanFactory,由图可知这是最顶层的抽象IOC容器

空构造器

(4)最后看看DefaultListableBeanFactory

其实这里可以发现采用大量的集合变量来保存一些涉及到的数据,所以看起来没有那么唬人。

3.XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);

接下来看看回调的过程

(1)

可见DefaultListableBeanFactory实现了BeanDefinitionRegistry类型的接口。

(2)调用父类AbstractBeanDefinitionReader,带有参数的构造器

为什么registry(也就是上面的factory)可能是ResourceLoader呢?其实这里是为ApplicationContext埋下了伏笔。

这个构造器主要干了三件事,一个是将registry绑定到factory,另外两个就是初始化ResourceLoader和environment(还不了解是干嘛的)。

4.reader.loadBeanDefinitions(res);

好吧,终于到了激动人心的载入BeanDefinition过程。

(1)loadBeanDefinitions(Resource resource)方法

应用装饰器模式,包装Resource。

(2)然后是调用的重载方法loadBeanDefinitions(EncodedResource encodedResource)

/**
* Load bean definitions from the specified XML file.
* @param encodedResource the resource descriptor for the XML file,
* allowing to specify an encoding to use for parsing the file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
//resourcesCurrentlyBeingLoaded是ThreadLocal类型的,里面保存的是Set类型。为了保证线程安全。
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
        //将encodeResource,资源放入存放资源的Set中
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
            //转换为输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
                //包装成InputSource类型的资源
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//最终调用doLoadBeanDefinitions方法。
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}

所以,每次看到的输出的载入xml bean definitions的log信息,就是来自这个方法。所以在loadBeanDefinition过程中,首先输出的信息来自这里。

(3) doLoadBeanDefinitions

而这个方法其实会调用doLoadDocument()方法获得Document,即W3C中说的document,即HTML文档或者XML文档等。得到的document对象并没有按照Spring规则解析。

而通过registerBeanDefinitions,启动对BeanDefinition的详细解析过程,这个解析过程涉及到了Spring的配置规则。

(4)registerBeanDefinitions,注册Bean,通过这个方法Spring会按照Bean语义要求进行解析,并转化为容器内部的数据结构(BeanDefinition),这个过程是在registerBeanDefinitions中进行的。而这个函数属于XMLBeanDefinitionReader。

/**
* Register the bean definitions contained in the given DOM document.
* Called by {@code loadBeanDefinitions}.
* <p>Creates a new instance of the parser class and invokes
* {@code registerBeanDefinitions} on it.
* @param doc the DOM document
* @param resource the resource descriptor (for context information)
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of parsing errors
* @see #loadBeanDefinitions
* @see #setDocumentReaderClass
* @see BeanDefinitionDocumentReader#registerBeanDefinitions
*/
@SuppressWarnings("deprecation")
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}

最终会调用BeanDefinitionDocumentReader的对象documentReader的registerBeanDefinitions方法,按照Spring的Bean定义规则进行解析,同时这里可以发现这里返回的是此次注册的Bean的个数。documentReader是默认设置好的DefaultBeanDefinitionReader。

(5)documentReader.registerBeanDefinitions()

可以看到log信息,开始”Loading bean definitions”,调用doRegisterBeanDefinitions(root)方法

(6)doRegisterBeanDefinitions()方法

/**
* Register each bean definition within the given root {@code <beans/>} element.
*/
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
return;
}
}
} preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root); this.delegate = parent;
}

好吧,还没到头,要注意这里有一个注释“

/**
     * Register each bean definition within the given root {@code <beans/>} element.
*/

”可以看出是从<beans>作为root节点进行解析。

可以看到有一个delegate对象,属于BeanDefinitionParserDelegate类型,而这个类的定义如下:

/**
* Stateful delegate class used to parse XML bean definitions.
* Intended for use by both the main parser and any extension
* {@link BeanDefinitionParser BeanDefinitionParsers} or
* {@link BeanDefinitionDecorator BeanDefinitionDecorators}.

可以看到这个类的作用主要是有状态的解析XML BeanDefinition的代理。

同时,由于每个bean可能存在层次关系,而引发递归调用,为了维护网络层次关系,采用parent属性保留其parent Bean.接下来看一下默认的delegate属性长什么样子?

可以重点看一下defaults的属性,如autowire是no,lazyInit=false。

parseBeanDefintions()将是解析BeanDefinition的最终方法?

(7)parseBeanDefinitions

/**
* Parse the elements at the root level in the document:
* "import", "alias", "bean".
* @param root the DOM root element of the document
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}

该方法属于DefaultBeanDefinitionDocumentReader,即前面得到的documentReader,是处理BeanDefinition的地方,具体的委托处理交给了BeanDefinitionParseDelegate来完成。

当子node是Element类型时,将触发parseDefaultElement(ele, delegate),继续解析,-》-》

(8)parseDefaultElement

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}

根据元素类型不同,调用的注册方法不同。这里调用processBeanDefinition(ele, delegate),这就涉及到了<beans>的三个子类别<import>,<alias>,<bean>

(9)processBeanDefinition

这个方法仍然属于DefaultBeanDefinitionDocumentReader。这里具体解析Bean元素。

/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}

这里会通过调用delegate的parseBeanDefinitionElement的方法,处理在xml文件中定义的<bean>,以及他的对应的属性。具体如下:

这里可以看到bean的id,name,alias等定义的属性元素。把这些元素取出来之后,设置到生成的BeanDefinitionHolder中。

debug查看beanDefinition的信息如下,这里可以看到一些默认的设置,比如abstract=false,lazyInit=false;autowireMode=0;等同时它的class属性也在这里。

Generic bean: class [com.wly.source.spring_scoure_inspect.Dancer]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [beans.xml]

可以看到BeanDefinition可以看成是对<bean>定义的抽象,是容器中的基本数据类型,封装了Bean所需要的所有的数据。可以看出它是及其重要的。

最好包装返回成BeanDefinitionHolder。Holder for a BeanDefinition with name and aliases.
Can be registered as a placeholder for an inner bean.BeanDefinitionHolder是BeanDefinition对象的封装类,封装了BeanDefinition的BeanDefinition,名字和别名(alias)。用它来完成IOC容器的注册。

最后,通过

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());完成最后的注册。

而这里通过getRegistry()方法得到的BeanDefinitionRegistry,即一开始得到的DefaultListableBeanFactory factory。这里进行回调使用,这也是为什么registerBeanDefinition方法属于BeanDefinitionReaderUtils的原因。

/**
* Register the given bean definition with the given bean factory.
* @param definitionHolder the bean definition including name and aliases
* @param registry the bean factory to register with
* @throws BeanDefinitionStoreException if registration failed
*/
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException { // Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}

通过回调registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); 完成将BeanDefinition注册进入factory。到这里解析的工作就完成了,接下来就是注册的过程,而注册方法属于DefaultListableBeanFactory。

(10)registry.registerBeanDefinition

//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
//由于DefaultListableBeanFactory 实现了BeanDefinitionRegistry接口,而该接口的一个重要方法就是registerBeanDefinition,来注册BeanDefinition到Factory。
    @Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
} BeanDefinition oldBeanDefinition;
//BeanDefinitonMap是保存BeanDefinition的地方,Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
//将Bean的name属性放入beanDefinitionNames中,该属性是一个ArrayList
            this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
this.frozenBeanDefinitionNames = null;
}
//这个是registry的核心过程,其实就是将BeanDefinition放入beanDefinitionMap中的过程。键是beanname,值是BeanDefinition.
        this.beanDefinitionMap.put(beanName, beanDefinition);

        if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

5.依赖注入的过程

以上过程可以看成是IOC容器初始化的过程,这个初始化过程完成的主要工作是完成BeanDefinition在IOC容器中的数据映射。而这里并没有实例化任何对象,也从来没有完成过依赖注入的过程。

依赖注入是通过getBean方法完成的,当然如果将lazy-init属性设置为true,则可以在初始化的过程中完成依赖注入,实现预实例化。

Performer performer=(Performer) factory.getBean("dancer");通过getBean获得名为“dancer”的对象,而factory现在保有的仅仅是键为“dancer”的BeanDefinition对象(保存在Map中)。

下面就一步步看看这个依赖注入,或者是IOC控制反转到底是怎么实现的。

(1)getBean(String name)

这个方法并不属于DefaultListableBeanFactory,而是属于其父类AbstractBeanFactory,这是一个抽象类,abstract类型。主要用来具体实现了BeanFactory接口。

//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//--------------------------------------------------------------------- @Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

可以看到具体的调用时doGetBean(String name)方法。

(2)doGetBean(String name)

/**
* Return an instance, which may be shared or independent, of the specified bean.
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException { final String beanName = transformedBeanName(name);
Object bean; // Eagerly check singleton cache for manually registered singletons.
// 先从缓存中获得bean,处理那些已经被创建过的单例bean,这种bean不在重复创建。
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
} // Check if bean definition exists in this factory.
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);
}
} if (!typeCheckOnly) {
markBeanAsCreated(beanName);
} try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
} // 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);
} else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
} // Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

1.其中getSingleton()的方法主要是从DefaultListableBeanFactory中的singletonObjects属性去get获取,其中该属性是一个ConcurrentHashMap,用来保存单例Bean实例。

2.对BeanDefinition是否存在进行检查,这里就涉及到了双亲BeanFactory,如果当前Factory中没有找到,则查找parentBeanFactory,并且沿着双亲链一直往上找。

3.注册实例化所有依赖的bean。通过registerDependentBean(dependsOnBean, beanName)注册所依赖的bean,getBean(dependsOnBean)实例化依赖的bean.这里其实存在递归的过程。

4.ObjectFactory,是一个泛型接口,只有一个方法,getObject(),返回一个实例。

5.由于Bean默认的scope是singleton,所以会通过调用getSingleton来回调createBean来产生sharedInstance。

(3)getSingleton(String beanName, ObjectFactory<?> singletonFactory)

值得注意的是ObjectFactory这里的参量命名就是singletonFactory.

singletonObject = singletonFactory.getObject();这是回调的方法函数.

而由上一步可知singletonFactory是一个匿名内部类,实现了ObjectFactory接口.其中只进行了createBean()一个步骤。

(4)createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

这个方法属于AbstractAutowireCapableBeanFactory,而由继承图知道AbstractAutowireCapableBeanFactory继承自AbstractBeanFactory抽象类,而createBean则是AbstractBeanFactory的一个抽象方法。

通过doCreateBean方法来实例化bean,在这之前会有一些列的处理过程。

(5)doCreateBean

/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// Instantiate the bean.
// 这个BeanWrapper是用来持有创建出来的bean对象的
        BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//createBeanInstance是真正创建bean的地方.
            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;
}
} // 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>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, 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.");
}
}
}
} // Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
} return exposedObject;
}

1.首先是BeanWrapper作为保存持有bean对象的对象

2.通过createBeanInstance()来创建bean

3.populateBean()装配Bean对象

(6)createBeanInstance

/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
*/
//对应实例化的三种方式,通过工厂方法实例化,通过构造器,简单实例化。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//实例化方式的选择可以通过mbd的参数来决定。这里是使用工厂方法的方式实例化。
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
} // Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
} // Need to determine the constructor...
//选择合适参数的构造器进行实例化,这里由于存在参数所以选择带有参数的构造器实例化
       Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
} // No special handling: simply use no-arg constructor.
       //默认无参构造器,一般采用CGLIB字节码生成器类库进行实例或者JVM的反射功能。
return instantiateBean(beanName, mbd);
}

(7)autowireConstructor

这里是具体应用带参数构造器实例化对象的方法,通过逐步跟进可以发现这里是通过利用反射的思想进行的,首先是确定需要的构造器以及构造器的参数,然后再通过构造器对象的newInstance方法。DefaultListableBeanFactory默认的实例化策略是采用CGLIB的方式进行。

(8)populateBean()

该方法属于AbstractAutowireCapableBeanFactory抽象类

首先如果存在自动装配类型,则按照自动装配类型进行解决自动装配的问题。分为by_Name或者By_Type。否则直接应用applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs)进行属性装配。接下来逐步跟踪applyProperty方法

(9)applyProperty()

该方法同样属于AbstractAutowireCapableBeanFactory抽象类。

/**
* Apply the given property values, resolving any runtime references
* to other beans in this bean factory. Must use deep copy, so we
* don't permanently modify this property.
* @param beanName the bean name passed for better exception information
* @param mbd the merged bean definition
* @param bw the BeanWrapper wrapping the target object
* @param pvs the new property values
*/
//其中三个形参分别为bean名称,BeanDefinition,Bean实例包装类,属性对象
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
} MutablePropertyValues mpvs = null;
List<PropertyValue> original; if (System.getSecurityManager() != null) {
if (bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
} if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
} TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values.
//这里有一个深拷贝,对每一个属性对象建立一个副本。
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
} // Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}

这里是处理属性进行依赖注入的过程,总的来看分为如下几步:

1.获得属性对象PropertyValue,对属性对象分别进行重新解析,解析之后再放入List deepcopy中。

2.其中涉及到了类型转换的问题,采用BeanDefinitionValueResolver进行类型转换的工作。resolveValueIfNecessary()这里对于ref类型,以及内部类的问题,都有相应的实例化处理过程。

public Object resolveValueIfNecessary(Object argName, Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
else if (value instanceof BeanDefinitionHolder) {
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
BeanDefinition bd = (BeanDefinition) value;
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
ObjectUtils.getIdentityHexString(bd);
return resolveInnerBean(argName, innerBeanName, bd);
}
...............
}

对于ref类型会出发getBean()方法,从而引发递归依赖注入;

而对于内部匿名类,本例子中就是,则会按照BeanDefinitionHolder进行处理,应用的方法是resolveInnerBean(),而这个方法会触发DefaultListableBeanFactory中的一些列的处理内部类的方法,同样也分为register和create。

3.调用BeanWrapper的setPropertyValues()方法进行依赖注入

(10)setPropertyValues()

setPropertyValues()会依次应用setPropertyValue()逐个属性进行装配。setPropertyValue(PropertyValue pv)方法属于BeanWrapperImpl

在这个方法中,分别对Array,List,Map,以及非集合类进行注入。

以非集合类为例,如String类型,该Bean有一个String属性名为name,而这个注入的过程就是通过反射获得setter,setName(String name)方法,然后invoke()实现。

四. 总结

这可能是分析源码学习过程中最难的一次经历,当然也是最有收获最有成就感的一次学习过程。

虽然从头捋顺清楚了IOC容器的实现原理,但是不得不说好多其内在的设计模式并没有完全领会,而且Spring框架的优秀之处,其对各种细节情况的处理也没有细致分析。

而且这并不是常用的例子,最为常用的应该还是各种ApplicationContext,下一步就是ApplicationContext的分析。

Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory的更多相关文章

  1. 转 Spring源码剖析——核心IOC容器原理

    Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...

  2. 【spring源码分析】IOC容器初始化(总结)

    前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...

  3. 【spring源码分析】IOC容器初始化(二)

    前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...

  4. 【spring源码分析】IOC容器初始化(三)

    前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...

  5. 【spring源码分析】IOC容器初始化(四)

    前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...

  6. 【spring源码分析】IOC容器初始化(七)

    前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...

  7. 【spring源码分析】IOC容器初始化(十)

    前言:前文[spring源码分析]IOC容器初始化(九)中分析了AbstractAutowireCapableBeanFactory#createBeanInstance方法中通过工厂方法创建bean ...

  8. 【spring源码分析】IOC容器初始化——查漏补缺(一)

    前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...

  9. Spring源码分析专题 —— IOC容器启动过程(上篇)

    声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...

随机推荐

  1. Struts2之Domain Model(域模型)。

    使用原因 为了避免在action中有太多的类,而需要写大量的get().set(). 故在Struts2 使用 了 domain model. Action: private User user; p ...

  2. 常用HQL(Hibernate Query Language)查询

    查询一个对象(实体类必须有一个不带参数的构造方法) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void test01() ...

  3. free 和delete 把指针怎么啦?

    别看 free 和 delete 的名字恶狠狠的(尤其是 delete),它们只是把指针所指的内存给 释放掉,但并没有把指针本身干掉. 发现指针 p 被 free 以后其地址仍然不变(非 NULL), ...

  4. Python的类和函数的魔法

    class CustomClass: def customFun(self, id): print("fun_1",id ) if __name__ == '__main__': ...

  5. JavaScript正则表达式1

    在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要.正则表达式就是用于描述这些规则的工具.换句话说,正则表达式就是记录文本规则的代码. 正则表达式可以: •数据有效性验证.可以 ...

  6. mysql数据库中,通过一条insert into语句,同时插入多个值

    需求描述: 今天在看一本mysql的书籍,发现一个mysql中insert into好用的技巧,就是通过 1条insert into语句,插入多行数据,而不是多个insert into语句.在此记录下 ...

  7. tiny4412 linux+qtopia nfs网络文件系统的挂载

    1,首先确定uboot启动内核的bootargs参数 Linux-CommandLine = root=/dev/nfs nfsroot=192.168.1.131:/home/tiny4412/ro ...

  8. oracle扩展dblink数。

    [标记]在进行数据迁移时:出现 Compilation errors for PROCEDURE ZDGAME.GFF_FETCH_MZR_LOG Error: ORA-04052: error oc ...

  9. linux中的目录和文件的统计

    ls 目录 | wc -l find  ./   -type   d   |   wc   -l      //查找目录个数 find   ./   -type   f   |   wc   -l   ...

  10. python文件和目录操作方法大全(含实例)【python】

    转自:http://www.jb51.net/article/48001.htm 一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法. 1.得到当前工作目录,即当前Py ...