Spring技术内幕2Spring Framework的核心:IoC容器的实现
2012-03-19 22:30
477 查看
1SpringIoC容器概述
IoC容器和依赖反转模式:
早在2004年,Martin Fowler就提出了“哪些方面的控制被反转了?”这个问题。他总结出是依赖对象的获得被反转了。基于这个结论,他为控制反转创造了一个更好的名字:依赖注入。许多非凡的应用(比HelloWorld.java更加优美,更加复杂)都是由两个或是更多的类通过彼此的合作来实现业务逻辑,这使得每个对象都需要,与其合作的对象(也就是它所依赖的对象)的引用。如果这个获取过程要靠自身实现,那么如你所见,这将导致代码高度耦合并且难以测试。
Spring IoC的应用场景:
在Spring中,Spring IoC提供了一个基本的JavaBean容器,通过IoC模式管理依赖关系,并通过依赖注入和AOP切面编程增强了为JavaBean这样的POJO对象赋予事务管理、生命周期管理等基本功能;
而对于EJB,一个简单的EJB组件需要编写远程/本地接口、Home接口以及Bean的实现类,而EJB运行是不能脱离EJB容器的,查找其他的EJB组件也需要诸如JNDI这样的方式,从而造成了对EJB容器和技术规范的 依赖。
2IoC容器系列的设计和实现:BeanFactory和ApplicationContext
两个主要的容器系列:
BeanFactory接口的实现,这个系列仅实现了容器的基本功能;The root interface for accessing a Spring bean container. This is the basic client view of a bean container;
ApplicationContext应用上下文,他作为容器的高级形态而存在。(此接口父接口HierarchicalBeanFactory也继承自BeanFactory)Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if the implementation supports this.
Spring的IoC容器系列:把IoC容器比喻成水桶,水桶有大小,作用也不同。
BeanDefinition:来管理基于Spring的应用中的各种对象以及他们之间的相互依赖关系,抽象了我们对Bean的定义,是容器起作用的主要数据类型。A BeanDefinition describes a bean instance, which has property values, constructor argument values, and further information supplied by concrete implementations.
Spring IoC容器设计:
如图:Spring IoC容器接口设计图.jpg
·从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路线。
BeanFactory接口定义了基本的IoC容器的规范。基本定义了获取bean和获取判断bean全局范围类型等。
HierarchicalBeanFactory,提供了getParentBeanFactory,使BeanFactory具备了双亲IoCring容器管理能力,和containsLocalBean(String name)两个方法。
ConfigurableBeanFactory,主要定义了一些对BeanFactory的配置功能。
·第两条接口设计主线是,以ApplicationContext应用上下文接口为核心的接口设计,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到ConfigurableApplicationContext或WebApplicationContext。
在这个接口体系中,ListableBeanFactory和HierarchicalBeanFactory两个接口,连接BeanFactory接口定义和ApplicationContext应用上下文的接口定义。
在ListableBeanFactory接口中,细化了许多BeanFactory接口功能。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver
·设计的主要接口关系,具体的IoC容器都是在这个接口体系下实现的,比如DefaultListableBeanFactory。
1、BeanFactory的应用场景
用户使用容器时,可以使用转义符"&"来得到FactoryBean本身。有了BeanFactory得到定义,可以进行一些额外的操作。
核心的getBean方法,又提供了一些对bean的判断等,bean数据都在BeanDefinition中定义。
2、BeanFactory容器的设计原理
我们可以从继承体系的发展上看到IoC容器各项功能的实现过程。
例子:XmlBeanFactory简历在DefaultListableBeanFactory基础上(ApplicationContext中也用到了他)。XmlBeanFactory利用XmlBeanDefinitionReader,通过方法loadBeanDefinitions(resource)读取以XML方法定义的BeanDefinition的IoC容器。通过Spring中的Resource I/O操作类,来获取XML形式定义的BeanDefinition。
3、ApplicationContext的应用场景
支持不同的信息源;访问资源;支持应用事件;在ApplicationContext中提供的附加服务。
4、ApplicationContext容器的设计原理
FileSystemXmlApplicationContext:
应用上下文的主要功能已经在基类AbstractXmlApplicationContext中实现了。
他本身只需要实现两个功能:在构造器中refresh();怎么从文件系统中加载XML的Bean定义资源。
3IoC容器的初始化过程
IoC容器的初始化是由refresh()方法来启动的。这个启动包括BeanDefinition的Resource定位、载入和注册三个基本过程。
Spring把这三个过程分开,并使用不同的模式来完成,可以灵活对这三个过程进行剪裁和扩展。
Resource定位:BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口来完成。
BeanDefinition载入:把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。
IoC容器注册这些BeanDefinition过程:通过调用BeanDefinitionRegistry接口的实现来完成。注册到一个HashMap中去。
这三个步骤不包含Bean依赖注入的实现。
Bean定义的载入和依赖注入是两个独立的过程。
依赖注入一般发生在第一次通过getBean向容器索取Bean的时候。(当设置lazyinit属性,这个Bean的依赖注入在IoC容器初始化时就预先完成。)
核心类:
org.springframework.context.support.AbstractApplicationContext:refresh()
Abstract implementation of the org.springframework.context.ApplicationContext interface. Doesn't mandate the type of storage used for configuration; simply implements common context functionality. Uses the Template Method design pattern, requiring concrete
subclasses to implement abstract methods.
org.springframework.context.support.AbstractRefreshableApplicationContext:createBeanFactory()
Base class for org.springframework.context.ApplicationContext implementations which are supposed to support multiple calls to refresh(), creating a new internal bean factory instance every time. Typically (but not necessarily), such a context will be driven
by a set of config locations to load bean definitions from.
org.springframework.beans.factory.support.DefaultListableBeanFactory:
Default implementation of the org.springframework.beans.factory.ListableBeanFactory and BeanDefinitionRegistry interfaces: a full-fledged bean factory based on bean definition objects.
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.
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 PropertiesBeanDefinitionReader
and org.springframework.beans.factory.xml.XmlBeanDefinitionReader.
org.springframework.beans.factory.xml.XmlBeanDefinitionReader:loadBeanDefinitions()
Bean definition reader for XML bean definitions. Delegates the actual XML document reading to an implementation of the BeanDefinitionDocumentReader interface.
Typically applied to a org.springframework.beans.factory.support.DefaultListableBeanFactory or a org.springframework.context.support.GenericApplicationContext.
This class loads a DOM document and applies the BeanDefinitionDocumentReader to it. The document reader will register each bean definition with the given bean factory, talking to the latter's implementation of the org.springframework.beans.factory.support.BeanDefinitionRegistry
interface.
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate:parseBeanDefinitionElement()
Stateful delegate class used to parse XML bean definitions. Intended for use by both the main parser and any extension BeanDefinitionParsers or BeanDefinitionDecorators.
1BeanDefinition的Resource定位:
使用DefaultListableBeanFactory时,首先定义一个Resource来定位容器使用的BeanDefinition。这时使用的是ClassPathResource。
基类DefaultResourceLoader提供了ResourceLoader读入以Resource定义的BeanDefinition的能力。这样就可以使DefaultListableBeanFactory从bean的定义资源方式中全身而退,做一个纯碎的IoC容器。
FileSystemXmlApplicationContext通过继承AbstractApplicationContext具备了ResourceLoader读入以及Resource定义的BeanDefinition能力,因为AbstractApplicationContext的基类是DefaultResourceLoader。
refresh()内部一处调用到了AbstractRefreshableApplicationContext的refreshBeanFactory(),这个方法通过createBeanFactory()构建了一个IoC容器供ApplicationContext使用。这个IoC容器就是上面的DefaultListableBeanFactory,同时,他启动了loadBeanDefinitions(beanFactory)来载入BeanDefinition。具体的资源载入在XmlBeanDefinitionReader读入BeanDefinition时完成。
2BeanDefinition的载入和解析:
IoC容器对Bean的管理和 依赖注入功能的实现,是通过其持有的BeanDefinition进行各种相关操作完成的。
IoC容器的refresh过程
如图:BeanDefinition载入中的交互过程.jpg
3BeanDefinition在IoC容器中的注册
如图:registerBeanDefinition的调用关系.jpg
完成了BeanDefinition的注册,就完成了IoC容器的初始化过程。此时DefaultListableBeanFactory容器中已经建立了整个Bean的配置信息,而这些BeanDefinition已经可以在容器使用了,这些信息就是容器建立依赖反转的基础。
4容器的依赖注入
getBean是依赖注入的起点,之后会调用createBean。
如图:依赖注入的过程.jpg
5容器其他相关特性的设计与实现
IoC容器和依赖反转模式:
早在2004年,Martin Fowler就提出了“哪些方面的控制被反转了?”这个问题。他总结出是依赖对象的获得被反转了。基于这个结论,他为控制反转创造了一个更好的名字:依赖注入。许多非凡的应用(比HelloWorld.java更加优美,更加复杂)都是由两个或是更多的类通过彼此的合作来实现业务逻辑,这使得每个对象都需要,与其合作的对象(也就是它所依赖的对象)的引用。如果这个获取过程要靠自身实现,那么如你所见,这将导致代码高度耦合并且难以测试。
Spring IoC的应用场景:
在Spring中,Spring IoC提供了一个基本的JavaBean容器,通过IoC模式管理依赖关系,并通过依赖注入和AOP切面编程增强了为JavaBean这样的POJO对象赋予事务管理、生命周期管理等基本功能;
而对于EJB,一个简单的EJB组件需要编写远程/本地接口、Home接口以及Bean的实现类,而EJB运行是不能脱离EJB容器的,查找其他的EJB组件也需要诸如JNDI这样的方式,从而造成了对EJB容器和技术规范的 依赖。
2IoC容器系列的设计和实现:BeanFactory和ApplicationContext
两个主要的容器系列:
BeanFactory接口的实现,这个系列仅实现了容器的基本功能;The root interface for accessing a Spring bean container. This is the basic client view of a bean container;
ApplicationContext应用上下文,他作为容器的高级形态而存在。(此接口父接口HierarchicalBeanFactory也继承自BeanFactory)Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if the implementation supports this.
Spring的IoC容器系列:把IoC容器比喻成水桶,水桶有大小,作用也不同。
BeanDefinition:来管理基于Spring的应用中的各种对象以及他们之间的相互依赖关系,抽象了我们对Bean的定义,是容器起作用的主要数据类型。A BeanDefinition describes a bean instance, which has property values, constructor argument values, and further information supplied by concrete implementations.
Spring IoC容器设计:
如图:Spring IoC容器接口设计图.jpg
·从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路线。
BeanFactory接口定义了基本的IoC容器的规范。基本定义了获取bean和获取判断bean全局范围类型等。
HierarchicalBeanFactory,提供了getParentBeanFactory,使BeanFactory具备了双亲IoCring容器管理能力,和containsLocalBean(String name)两个方法。
ConfigurableBeanFactory,主要定义了一些对BeanFactory的配置功能。
·第两条接口设计主线是,以ApplicationContext应用上下文接口为核心的接口设计,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到ConfigurableApplicationContext或WebApplicationContext。
在这个接口体系中,ListableBeanFactory和HierarchicalBeanFactory两个接口,连接BeanFactory接口定义和ApplicationContext应用上下文的接口定义。
在ListableBeanFactory接口中,细化了许多BeanFactory接口功能。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver
·设计的主要接口关系,具体的IoC容器都是在这个接口体系下实现的,比如DefaultListableBeanFactory。
1、BeanFactory的应用场景
用户使用容器时,可以使用转义符"&"来得到FactoryBean本身。有了BeanFactory得到定义,可以进行一些额外的操作。
核心的getBean方法,又提供了一些对bean的判断等,bean数据都在BeanDefinition中定义。
2、BeanFactory容器的设计原理
我们可以从继承体系的发展上看到IoC容器各项功能的实现过程。
例子:XmlBeanFactory简历在DefaultListableBeanFactory基础上(ApplicationContext中也用到了他)。XmlBeanFactory利用XmlBeanDefinitionReader,通过方法loadBeanDefinitions(resource)读取以XML方法定义的BeanDefinition的IoC容器。通过Spring中的Resource I/O操作类,来获取XML形式定义的BeanDefinition。
3、ApplicationContext的应用场景
支持不同的信息源;访问资源;支持应用事件;在ApplicationContext中提供的附加服务。
4、ApplicationContext容器的设计原理
FileSystemXmlApplicationContext:
应用上下文的主要功能已经在基类AbstractXmlApplicationContext中实现了。
他本身只需要实现两个功能:在构造器中refresh();怎么从文件系统中加载XML的Bean定义资源。
3IoC容器的初始化过程
IoC容器的初始化是由refresh()方法来启动的。这个启动包括BeanDefinition的Resource定位、载入和注册三个基本过程。
Spring把这三个过程分开,并使用不同的模式来完成,可以灵活对这三个过程进行剪裁和扩展。
Resource定位:BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口来完成。
BeanDefinition载入:把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。
IoC容器注册这些BeanDefinition过程:通过调用BeanDefinitionRegistry接口的实现来完成。注册到一个HashMap中去。
这三个步骤不包含Bean依赖注入的实现。
Bean定义的载入和依赖注入是两个独立的过程。
依赖注入一般发生在第一次通过getBean向容器索取Bean的时候。(当设置lazyinit属性,这个Bean的依赖注入在IoC容器初始化时就预先完成。)
核心类:
org.springframework.context.support.AbstractApplicationContext:refresh()
Abstract implementation of the org.springframework.context.ApplicationContext interface. Doesn't mandate the type of storage used for configuration; simply implements common context functionality. Uses the Template Method design pattern, requiring concrete
subclasses to implement abstract methods.
org.springframework.context.support.AbstractRefreshableApplicationContext:createBeanFactory()
Base class for org.springframework.context.ApplicationContext implementations which are supposed to support multiple calls to refresh(), creating a new internal bean factory instance every time. Typically (but not necessarily), such a context will be driven
by a set of config locations to load bean definitions from.
org.springframework.beans.factory.support.DefaultListableBeanFactory:
Default implementation of the org.springframework.beans.factory.ListableBeanFactory and BeanDefinitionRegistry interfaces: a full-fledged bean factory based on bean definition objects.
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.
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 PropertiesBeanDefinitionReader
and org.springframework.beans.factory.xml.XmlBeanDefinitionReader.
org.springframework.beans.factory.xml.XmlBeanDefinitionReader:loadBeanDefinitions()
Bean definition reader for XML bean definitions. Delegates the actual XML document reading to an implementation of the BeanDefinitionDocumentReader interface.
Typically applied to a org.springframework.beans.factory.support.DefaultListableBeanFactory or a org.springframework.context.support.GenericApplicationContext.
This class loads a DOM document and applies the BeanDefinitionDocumentReader to it. The document reader will register each bean definition with the given bean factory, talking to the latter's implementation of the org.springframework.beans.factory.support.BeanDefinitionRegistry
interface.
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate:parseBeanDefinitionElement()
Stateful delegate class used to parse XML bean definitions. Intended for use by both the main parser and any extension BeanDefinitionParsers or BeanDefinitionDecorators.
1BeanDefinition的Resource定位:
使用DefaultListableBeanFactory时,首先定义一个Resource来定位容器使用的BeanDefinition。这时使用的是ClassPathResource。
基类DefaultResourceLoader提供了ResourceLoader读入以Resource定义的BeanDefinition的能力。这样就可以使DefaultListableBeanFactory从bean的定义资源方式中全身而退,做一个纯碎的IoC容器。
FileSystemXmlApplicationContext通过继承AbstractApplicationContext具备了ResourceLoader读入以及Resource定义的BeanDefinition能力,因为AbstractApplicationContext的基类是DefaultResourceLoader。
refresh()内部一处调用到了AbstractRefreshableApplicationContext的refreshBeanFactory(),这个方法通过createBeanFactory()构建了一个IoC容器供ApplicationContext使用。这个IoC容器就是上面的DefaultListableBeanFactory,同时,他启动了loadBeanDefinitions(beanFactory)来载入BeanDefinition。具体的资源载入在XmlBeanDefinitionReader读入BeanDefinition时完成。
AbstractRefreshableApplicationContext: /** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. */ @Override protected final void refreshBeanFactory() throws BeansException { //这里判断,如果已经建立BeanFactory,则销毁并关闭该BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } //这里是创建并设置持有的DefaultListableBeanFactory的地方同时调用loadBeanDefinitions(beanFactory)再载入BeanDefinition的信息。 try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } /** * Create an internal bean factory for this context. * Called for each {@link #refresh()} attempt. * <p>The default implementation creates a * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory} * with the {@linkplain #getInternalParentBeanFactory() internal bean factory} of this * context's parent as parent bean factory. Can be overridden in subclasses, * for example to customize DefaultListableBeanFactory's settings. * @return the bean factory for this context * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping */ //这就是在上下文中创建DefaultListableBeanFactory的地方,而getInternalParentBeanFactory()会根据容器已有的双亲IoC容器的信息来生成DefaultListableBeanFactory的双亲IoC容器。 protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); } /** * Load bean definitions into the given bean factory, typically through * delegating to one or more bean definition readers. * @param beanFactory the bean factory to load bean definitions into * @throws BeansException if parsing of the bean definitions failed * @throws IOException if loading of bean definition files failed * @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader */ //这里是使用BeanDefinitionReader载入Bean定义的地方,因为允许有多种载入方式,虽然用的最多的是XML定义的形式,这里同一个一个抽象函数把具体的实现委托给子类来完成。 protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException; 父类loadBeanDefinitions实现: AbstractXmlApplicationContext:loadBeanDefinitions(DefaultListableBeanFactory beanFactory) /** * Loads the bean definitions via an XmlBeanDefinitionReader. * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader * @see #initBeanDefinitionReader * @see #loadBeanDefinitions */ @Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } //DefaultResourceLoader对于取得Resource的具体过程 public Resource getResource(String location) { Assert.notNull(location, "Location must not be null"); if (location.startsWith(CLASSPATH_URL_PREFIX)) { return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); } else { try { // Try to parse the location as a URL... URL url = new URL(location); return new UrlResource(url); } catch (MalformedURLException ex) { // No URL -> resolve as resource path. return getResourceByPath(location); } } }
2BeanDefinition的载入和解析:
IoC容器对Bean的管理和 依赖注入功能的实现,是通过其持有的BeanDefinition进行各种相关操作完成的。
IoC容器的refresh过程
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //这里是在子类中启动refreshBeanFactory()的地方 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //设置BeanFactory的后置处理 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //调用BeanFactory的后处理器,这些后处理器是在Bean定义中向容器注册的 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //注册Bean的后处理器,在bean的创建过程中被调用 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //对上下文中的消息源进行初始化 initMessageSource(); // Initialize event multicaster for this context. //初始化上下文中的事件机制 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //初始化其他的特殊bean onRefresh(); // Check for listener beans and register them. //检查监听bean并且将这些bean向容器注册 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //实例化所有的(non-lazy-init)单例 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //发布容器事件,结束Refresh过程 finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } } protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //创建IoC容器,这使用的是DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); //启动对BeanDefinition的载入 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
如图:BeanDefinition载入中的交互过程.jpg
具体的载入实现没在AbstractRefreshApplicationContext中实现在 AbstractXmlApplicationContext:loadBeanDefinitions(DefaultListableBeanFactory beanFactory) /** * Loads the bean definitions via an XmlBeanDefinitionReader. * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader * @see #initBeanDefinitionReader * @see #loadBeanDefinitions */ @Override //这里是实现loadBeanDefinitions的地方 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. //创建XmlBeanDefinitionReader,并通过回调设置到BeanFactory中去 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); //设置父类DefaultResourceLoader beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. //启动bean定义信息载入过程 initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } /** * Load the bean definitions with the given XmlBeanDefinitionReader. * <p>The lifecycle of the bean factory is handled by the {@link #refreshBeanFactory} * method; hence this method is just supposed to load and/or register bean definitions. * @param reader the XmlBeanDefinitionReader to use * @throws BeansException in case of bean registration errors * @throws IOException if the required XML document isn't found * @see #refreshBeanFactory * @see #getConfigLocations * @see #getResources * @see #getResourcePatternResolver */ protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { //以Resource的方式获得配置文件的资源位置 Resource[] configResources = getConfigResources(); if (configResources != null) { //开始进行BeanDefinition的载入 reader.loadBeanDefinitions(configResources); } //以String的形式获得配置文件的位置 String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } } 而这时XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader已经为BeanDefinition的载入做好了准备。 public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { //如果Resource为空,则停止BeanDefinition的载入 Assert.notNull(resources, "Resource array must not be null"); int counter = 0; //启动BeanDefinition的载入过程,会便利Resource集合所有包含BeanDefinition信息 for (Resource resource : resources) { counter += loadBeanDefinitions(resource); } return counter; } /** * 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 */ //载入XML形式的BeanDefinition的地方 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()); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } //这里得到XML文件,并得到IO的InputResource准备进行读取 try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } 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(); } } } /** * Actually load bean definitions from the specified XML file. * @param inputSource the SAX InputSource to read from * @param resource the resource descriptor for the XML file * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors */ //具体的读取过程是在doLoadBeanDefinitions方法中找到 //这里从特定的XML文件中实际载入BeanDefinition的地方 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); //取得XML的Document对象 Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); //启动是对BeanDefinition解析的详细过程,这个解析会使用到Spring的Bean配置规则 return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } } /** * Register the bean definitions contained in the given DOM document. * Called by <code>loadBeanDefinitions</code>. * <p>Creates a new instance of the parser class and invokes * <code>registerBeanDefinitions</code> 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 */ public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //得到BeanDefinitionDocumentReader来对XML的BeanDefinition进行解析 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); int countBefore = getRegistry().getBeanDefinitionCount(); //具体解析过程 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } /** * Process the given bean element, parsing the bean definition * and registering it with the registry. */ //处理BeanDefinition的地方,具体的处理委托给BeanDefinitionParserDelegate来完成,ele对应在Spring BeanDefinition中定义的XML元素 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //BeanDefinitionHolder是BeanDefinition对象的封装类,封装了BeanDefinition,Bean的名字和别名。 //用他来完成向IoC容器注册。 //得到这个BeanDefinitionHolder就意味着BeanDefinition是通过BeanDefinitionParserDelegate对XML元素的信息按照Spring的Bean规则进行解析得到的 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)); } } /** * Parses the supplied <code><bean></code> element. May return <code>null</code> * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. */ public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { //这里取得在<bean>元素中定义的id、name和aliase属性的值 String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<String>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } //这个方法会引发对Bean元素的详细解析 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); // Register an alias for the plain bean class name, if still possible, // if the generator returned the class name plus a suffix. // This is expected for Spring 1.2/2.0 backwards compatibility. String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
3BeanDefinition在IoC容器中的注册
如图:registerBeanDefinition的调用关系.jpg
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); } } //注册的过程需要synchronized,保证数据的一致性 synchronized (this.beanDefinitionMap) { //检查是否已经存在相同名称的注册,如果已经存在,抛出异常 Object oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!this.allowBeanDefinitionOverriding) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } } //注册动作,先把名称放到beanDefinitionNames中,然后键值存入beanDefinitionMap else { this.beanDefinitionNames.add(beanName); this.frozenBeanDefinitionNames = null; } this.beanDefinitionMap.put(beanName, beanDefinition); resetBeanDefinition(beanName); } }
完成了BeanDefinition的注册,就完成了IoC容器的初始化过程。此时DefaultListableBeanFactory容器中已经建立了整个Bean的配置信息,而这些BeanDefinition已经可以在容器使用了,这些信息就是容器建立依赖反转的基础。
4容器的依赖注入
从AbstractBeanFactory的doGetBean入手: /** * Return an instance, which may be shared or independent, of the specified bean. * @param name the name of the bean to retrieve * @param requiredType the required type of the bean to retrieve * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. It is invalid to use a non-null args value in any other case. * @param typeCheckOnly whether the instance is obtained for a type check, * not for actual use * @return an instance of the bean * @throws BeansException if the bean could not be created */ @SuppressWarnings("unchecked") //这是实际取得Bean的地方,也是触发依赖注入发生的地方 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 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 + "'"); } } //Get the object for the given bean instance, either the bean instance itself or its created object in case of a FactoryBean. //完成的是FactoryBean的相关处理,以取得factoryBean的生产结果 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. //对IoC容器中的BeanDefinition是否存在进行检查,检查是否能在当前的BeanFactory中取得需要的Bean。 //如果当前工厂取不到,则到双亲BeanFactory中去取;如果当前的双亲工厂取不到,就顺着双亲BeanFactory链一直向上查找。 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); } //根绝Bean的名字取得BeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. //获得当前Bean的所有依赖Bean,这样会触发getBean的递归调用,直到取到一个没有任何依赖的Bean为止 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // Create bean instance. //这里通过调用createBean方法创建Singleton bean的实例,这里有一个回调函数getObject,会在getSingleton中带哦用ObjectFactory的createBean。 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { 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); } //这里是创建prototype bean的地方 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>() { 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); } } } // Check if required type matches the type of the actual bean instance. //这里对创建的Bean进行类型检查,如果没有问题,就返回这个新创建的Bean,这个Bean已经是包含了依赖关系的Bean 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; }
getBean是依赖注入的起点,之后会调用createBean。
如图:依赖注入的过程.jpg
AbstractAutowireCapableBeanFactory: /** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */ @Override protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } // Make sure bean class is actually resolved at this point. //这里判断需要创建的bean是否可以实例化,这个类是否可以通过类装载器来载入 resolveBeanClass(mbd, beanName); // Prepare method overrides. try { mbd.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. //如果Bean配置了PostProcessor,那么这里返回是一个proxy Object bean = resolveBeforeInstantiation(beanName, mbd); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } Object beanInstance = doCreateBean(beanName, mbd, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } /** * Actually create the specified bean. Pre-creation processing has already happened * at this point, e.g. checking <code>postProcessBeforeInstantiation</code> callbacks. * <p>Differentiates between default bean instantiation, use of a * factory method, and autowiring a constructor. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. This parameter must be <code>null</code> except in this case. * @return a new instance of the bean * @throws BeanCreationException if the bean could not be created * @see #instantiateBean * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. //这个BeanWrapper是用来持有创建出来的Bean对象的 BeanWrapper instanceWrapper = null; //如果是isSingleton,先把缓存中的同名Bean清除 if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } //由createBeanInstance创建bean if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } // 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() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. //这里是bean的初始化,依赖注入往往在这里发生,这个exposedObject在初始化处理完以后会返回作为依赖注入完成后的bean 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; } 这里,与依赖注入关系特别密切的方法有createBeanInstance和populateBean。 Bean包含的Java对象的生成: /** * Create a new instance for the specified bean, using an appropriate instantiation strategy: * factory method, constructor autowiring, or simple instantiation. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. It is invalid to use a non-null args value in any other case. * @return BeanWrapper for the new instance * @see #instantiateUsingFactoryMethod * @see #autowireConstructor * @see #instantiateBean */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // Make sure bean class is actually resolved at this point. //确定需要创建爱的Bean实例的类可以实例化 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()); } //使用工厂方法对Bean进行实例化 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. //是有默认的构造器对类进行实例化 return instantiateBean(beanName, mbd); } /** * Instantiate the given bean using its default constructor. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return BeanWrapper for the new instance */ //最常用的实例化过程instantiateBean //默认的实例化方式CGLIB: ///** Strategy for creating bean instances */ //private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return getInstantiationStrategy().instantiate(mbd, beanName, parent); } }, getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } } 提供了两种实例化Java对象方法:一种通过BeanUtils,使用了JVM的反射功能,一种是通过CGLIB。 public class SimpleInstantiationStrategy implements InstantiationStrategy { private static final ThreadLocal<Method> currentlyInvokedFactoryMethod = new ThreadLocal<Method>(); public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (beanDefinition.getMethodOverrides().isEmpty()) { //这里取得指定的构造器或者生成对象的工厂方法来对Bean进行实例化 Constructor<?> constructorToUse; synchronized (beanDefinition.constructorArgumentLock) { constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class clazz = beanDefinition.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() { public Constructor run() throws Exception { return clazz.getDeclaredConstructor((Class[]) null); } }); } else { constructorToUse = clazz.getDeclaredConstructor((Class[]) null); } beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Exception ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } //通过BeanUtils进行实例化,这个BeanUtils的实例化通过Constructor来实例化Bean return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. //使用CGLIB进行实例化 return instantiateWithMethodInjection(beanDefinition, beanName, owner); } } Bean对象生成以后,还需要对这些Bean的依赖关系设置好: /** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param bw BeanWrapper with bean instance */ protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { //获得BeanDefinition的各种属性 PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } //开始进行依赖注入过程 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } //对属性进行依赖注入 applyPropertyValues(beanName, mbd, bw, pvs); } 还有就是具体的实现....
5容器其他相关特性的设计与实现
1ApplicationContext和Bean的初始化及销毁: AbstractApplicationContext: // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); //Actually performs context closing: publishes a ContextClosedEvent and destroys the singletons in the bean factory of this application context. //Called by both close() and a JVM shutdown hook, if any. doClose() Spring IoC在对Bean的生命周期进行管理时提供了Bean生命周期各个时间点的回调。 AbstractAutowireCapableBeanFactory: /** * Initialize the given bean instance, applying factory callbacks * as well as init methods and bean post processors. * <p>Called from {@link #createBean} for traditionally defined beans, * and from {@link #initializeBean} for existing bean instances. * @param beanName the bean name in the factory (for debugging purposes) * @param bean the new bean instance we may need to initialize * @param mbd the bean definition that the bean was created with * (can also be <code>null</code>, if given an existing bean instance) * @return the initialized bean instance (potentially wrapped) * @see BeanNameAware * @see BeanClassLoaderAware * @see BeanFactoryAware * @see #applyBeanPostProcessorsBeforeInitialization * @see #invokeInitMethods * @see #applyBeanPostProcessorsAfterInitialization */ protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } 在这个方法中使用了很多invoke。invokeInitMethods--invokeCustomInitMethod 然后通过method反射调用 /** * Invoke the specified custom init method on the given bean. * Called by invokeInitMethods. * <p>Can be overridden in subclasses for custom resolution of init * methods with arguments. * @see #invokeInitMethods */ protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { String initMethodName = mbd.getInitMethodName(); final Method initMethod = (mbd.isNonPublicAccessAllowed() ? BeanUtils.findMethod(bean.getClass(), initMethodName) : ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName)); if (initMethod == null) { if (mbd.isEnforceInitMethod()) { throw new BeanDefinitionValidationException("Couldn't find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'"); } else { if (logger.isDebugEnabled()) { logger.debug("No default init method named '" + initMethodName + "' found on bean with name '" + beanName + "'"); } // Ignore non-existent default lifecycle methods. return; } } if (logger.isDebugEnabled()) { logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { ReflectionUtils.makeAccessible(initMethod); return null; } }); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { initMethod.invoke(bean); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { InvocationTargetException ex = (InvocationTargetException) pae.getException(); throw ex.getTargetException(); } } else { try { ReflectionUtils.makeAccessible(initMethod); initMethod.invoke(bean); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } /** * Make the given method accessible, explicitly setting it accessible if * necessary. The <code>setAccessible(true)</code> method is only called * when actually necessary, to avoid unnecessary conflicts with a JVM * SecurityManager (if active). * @param method the method to make accessible * @see java.lang.reflect.Method#setAccessible */ public static void makeAccessible(Method method) { if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { method.setAccessible(true); } } DisposableBeanAdapter:close(); 2lazy-init属性和预实例化 在finishBeanFactoryInitialization(beanFactory)方法中,封装了对lazy-init属性的处理,实际的的处理是在DefaultListableBeanFactory这个基本容器的preInstantiateSingletons()方法中完成的。 3FactoryBean的实现 FactoryBean的生产特性是在getBean中起作用。而本身的机制类似于AbstractFactory抽象工厂。 4BeanPostProcessor的实现 这个后置处理器是一个监听器,可以监听容器触发的时间。 在前面的initializeBean方法中有两句代码执行了这个后置处理器: wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 5autowiring、@Autowired AbstractAutowireCapableBeanFactory的populateBean方法中: if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } 6Bean的依赖检查 在AbstractAutowireCapableBeanFactory creatBean的过程中检查的 7Bean对IoC容器的感知 某些情况下需要在Bean中直接对IoC容器进行操作,这时候,就需要在Bean中定义对容器的感知,通过特定的aware接口来完成。 ApplicationContextAwareProcessor implements BeanPostProcessor,对一系列的aware回调进行调用。作为依赖注入的一部分,postProcessBeforeInitialization会在initializeBean的实现过程中被调用。
相关文章推荐
- Spring技术核心内幕 读书笔记--IOC容器的实现小结
- Spring技术内幕之IOC容器的实现(01)-IOC容器初始化过程
- Spring技术内幕总结 - IoC容器的实现
- 读《Spring-技术内幕》-第二章:IoC容器的实现-1
- Spring技术内幕——Spring Framework的IOC容器实现(二)
- Spring技术内幕笔记 -- IoC容器的实现
- Spring技术内幕——Spring Framework的IOC容器实现(三)
- Spring技术内幕——Spring Framework的IOC容器实现(五)(大结局)
- 读《Spring-技术内幕》-第二章:IoC容器的实现-2
- spring技术内幕之IoC容器的实现
- Spring技术内幕——Spring Framework的IOC容器实现(四)
- Spring技术内幕——IoC容器的实现
- Spring技术内幕之IOC容器的实现(02)-BeanDefinition的Resource定位
- Spring技术内幕——Spring Framework的IOC容器实现(一)
- Spring核心技术IoC容器(六)
- Spring技术内幕——深入解析Spring架构与设计原理(一)IOC实现原理
- Spring核心IOC容器实现分析
- Spring核心技术IoC容器(五)
- Spring技术内幕——深入解析Spring架构与设计原理(一)IOC实现原理
- spring技术内幕笔记:IoC容器的初始化过程(3)- BeanDefinition的注册