Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory
从这个继承体系结构图来看,我们可以发现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(); } } }
(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中,该属性是一个ArrayListthis.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的分析。