Spring容器的本质
阿里妹导读
一、问题
5、Spring容器设计思想?
二、关键词
三、全文概要
Spring容器本质上就是一个存放了一个个描述不同对象属性和方法的定义单元,需要使用的时候就通过反射机制把对象创建好,再将描述的属性初始化。其中涉及了一系列精妙的设计模式和实现思路,这给我们写标准的优质代码提供了绝佳的模板。本文力求讨论Spring容器最核心的机制,用最少的代码讲清楚Spring容器的本质。
四、架构
4.1 Spring整体架构
上图是Spring框架的整体架构,从架构图我们可以看出来Spring的根基就是core container,就是我们说的IOC容器。在此基础上才有AOP,DATA和WEB的繁荣,本章我们讨论的是Spring家族的基石,Spring容器,也就是我们上文提到的IOC容器。所有其他的Spring组件都是在容器上构建出来的,所以我们暂时去掉所有其他的组件功能介绍,只讨论IOC容器。
Spring容器最核心的三个jar包是bean,context,core。bean是Spring基石,一切皆为bean,context维护了应用的上下文,如果bean是演员,那么context就是舞台,而core则是道具。
4.1 上下文ApplicationConext
publicinterfaceApplicationContextextendsEnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver{String getId();String getApplicationName();String getDisplayName();longgetStartupDate();ApplicationContext getParent();AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
ApplicationConext:从类图的继承关系我们看到基础类ApplicationConext继承了资源,消息,事件,环境,工厂五种能力,ApplicationConext只包含了简单的只读属性。 ConfigurableApplicationContext:继承了生命周期管控能力,同时继承ApplicationConext,拓展了context的环境,事件等写的属性。
AbstractApplicationContext:大部分的能力在该类定义实现,该类继承类加载能力接口DefaultResourceLoader和读写context的ConfigurableApplicationContext,ioc容器启动的流程详细解析该类。
GenericApplicationContext:通用上下文。
AnnotationConfigApplicationContext:注解可配置上下文。
GenericGroovyApplicationContext:groovy配置文件上下文。
GenericXmlApplicationContext:通用xml配置文件上下文。
StaticApplicationContext:消息可读取上下文。
AbstractRefreshableApplicationContext:可刷新可配置化上下文。
AbstractRefreshableConfigApplicationContext:可刷新可配置化上下文。
AbstractXmlApplicationContext:xml配置文件类型的上下文。
ClassPathXmlAp-plicationContext:终端类路径xml上下文。
FileSystemXmlApplicationContext:文件系统xml上下文。
4.2 BeanFactory
Spring的世界一切皆为bean。
AliasRegistry:别名注册表 BeanFactory:工厂 BeanDefinitionRegistry:定义
DefaultListableBeanFactory这个收敛了所以上层的能力,具体包含核心的BeanDefinitionRegistry和BeanFactory,也就是bean的定义和生产bean的工厂。
五、过程
容器启动核心过程如下图,包含容器读取配置文件后创建对象,然后对象属性初始化的过程:
5.1 启动容器
我们要探究Spring最核心的容器原理,就要先排除其他高级属性的干扰,只依赖最少的jar包来构建工程,然后一步步跟踪容器启动的过程。
构建工程:新建java工程,引入最少所需依赖的Spring包;
新建测试启动类Application
package com.alibaba.spring;import com.alibaba.spring.beans.Producer;import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author Lin ZhenHua*/public class Application{public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Producer producer = context.getBean(Producer.class);System.out.println("running the test case with name = " + producer.getCount());}}
新建spring配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean name="producer"class="com.alibaba.spring.beans.Producer"><property name="count"value="10" /></bean></beans>
执行结果
七月 10, 2018 11:31:16 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5197848c: startup date [Tue Jul 10 11:31:16 CST 2018]; root of context hierarchy七月 10, 2018 11:31:17 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions信息: Loading XML bean definitions from class path resource [applicationContext.xml]running the test case with name = 10
经过以上几个步骤,我们成功地将配置文件里面描述的对象,通过Spring的IOC容器创建了出来,而且不需要再使用new的形式来创建对象,下面我们将深入解析IOC容器的工作流程。
5.2 入口
创建Spring容器上下文对象,调用ClassPathXmlApplicationContext构造函数,传入配置文件路径参数;
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");/*** loading the definitions* from the given XML file and automatically refreshing the context*/publicClassPathXmlApplicationContext(String configLocation) throws BeansException {this(new String[] {configLocation}, true, null);}publicClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {super(parent);setConfigLocations(configLocations);if (refresh) {refresh(); //核心方法}}
调用refresh()方法启动IOC容器;
/*** Load or refresh the persistent representation of the configuration*/public void refresh() throws BeansException, IllegalStateException {//容器重启同步监控锁,防止刷新进行到一半被重复执行synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.//填充配置文件占位符,记录容器启动时间和启动状态prepareRefresh();//完成配置文件定义到注册表登记bean的流程,此时对象还未被创建// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.//配置类加载器,定制特殊bean,添加BeanPostProcessor可供回调prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.//工厂加载完配置,初始化之前回调PostProcessBeanFactory,作为工厂扩展功能postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.//调用上文注册的扩展接口PostProcessBeanFactory的实现,为扩展接口为列表类型invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.// bean扩展:postProcessBeforeInitialization和postProcessAfterInitialization//分别在Bean初始化之前和初始化之后得到执行registerBeanPostProcessors(beanFactory);// Initialize message source for this context.//初始化MessageSource对象,国际化initMessageSource();// Initialize event multicaster for this context.//初始化事件广播器initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.//临时钩子方法,提供一些初始化完成前的特殊操作,传送门onRefresh();// Check for listener beans and register them.//注册监听器registerListeners();// Instantiate all remaining (non-lazy-init) singletons.//实例化工厂注册表里面的bean(懒加载的除外,用到才实例化)finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.//初始化生命周期,广播事件finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}
5.3 准备工作
容器初始化之前的初始化工作;
protected void prepareRefresh() {this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);if (logger.isInfoEnabled()) {logger.info("Refreshing " + this);}// Initialize any placeholder property sources in the context environment//初始化占位符initPropertySources();// Validate that all properties marked as required are resolvable// see ConfigurablePropertyResolver#setRequiredProperties//校验配置文件getEnvironment().validateRequiredProperties();// Allow for the collection of early ApplicationEvents,// to be published once the multicaster is available...this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();}
5.4 创建BeanFactory
创建BeanFactory,这个是整个IOC容器启动流程的两大核心模块之一;
//AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {//关闭旧工厂,创建新工厂refreshBeanFactory();//返回创建的新工厂ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (logger.isDebugEnabled()) {logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);}return beanFactory;}
重置BeanFactory,存在则销毁,不存在则创建;
//AbstractRefreshableApplicationContext.java 120
@OverrideprotectedfinalvoidrefreshBeanFactory() throws BeansException {//存在BeanFactory()则销毁,即清除工厂里面Map存放的对象if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {//返回新建的DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();//工厂标识idbeanFactory.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);}}
创建BeanFactory,构造出子类对象DefaultListableBeanFactory,从前文架构部分我们可以看出这个类的重要地位,里面涵盖了工厂BeanFactory,对象定义BeanDefinition,和注册表AliasRegistry的能力,是一个完整的对象工厂,下文就是使用该工厂将配置文件的信息转换为类定义信息,再进行对象创建,属性赋值。
//AbstractRefreshableApplicationContext.java 199
protected DefaultListableBeanFactory createBeanFactory() {return new DefaultListableBeanFactory(getInternalParentBeanFactory());}
5.5 读取配置文件
读取xml配置文件
//AbstractXmlApplicationContext.java 80
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory.//实例化一个工厂类的XML文件阅读器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.//开启xml文件校验,可在实现的子类关闭initBeanDefinitionReader(beanDefinitionReader);//beanDefinitionReader阅读器加载资源文件loadBeanDefinitions(beanDefinitionReader);}
加载资源文件
//AbstractXmlApplicationContext.java 120
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {Resource[] configResources = getConfigResources();if (configResources != null) {reader.loadBeanDefinitions(configResources);}//configLocations最终解析成资源对象configResources,效果跟上面分支一样String[] configLocations = getConfigLocations();if (configLocations != null) {reader.loadBeanDefinitions(configLocations);}}
循环加载所有资源文件
//AbstractBeanDefinitionReader.java 177
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {Assert.notNull(resources, "Resource array must not be null");int counter = 0;for (Resource resource : resources) {counter += loadBeanDefinitions(resource);}return counter;}
阅读器从资源对象获取路径,读取配置文件
//XmlBeanDefinitionReader.java 303
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {return loadBeanDefinitions(new EncodedResource(resource));}
//XmlBeanDefinitionReader.java 314
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());}//使用ThreadLocal存放配置文件路径Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();if (currentResources == null) {currentResources = new HashSet<EncodedResource>(4);this.resourcesCurrentlyBeingLoaded.set(currentResources);}if (!currentResources.add(encodedResource)) {thrownew BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");}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) {thrownew BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), ex);}finally {currentResources.remove(encodedResource);if (currentResources.isEmpty()) {this.resourcesCurrentlyBeingLoaded.remove();}}}
读取配置文件内容
//XmlBeanDefinitionReader.java 388
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {//xml文件生成Document文件数Document doc = doLoadDocument(inputSource, resource);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);}}
5.6 注册对象
注册对象,将XML配置文件描述的Bean转换到BeanFactory的注册表上,返回增量的bean数量;
//XmlBeanDefinitionReader.java 505
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//注册表已存在Definition数量(对象的描述)int countBefore = getRegistry().getBeanDefinitionCount();//将doc树的bean定义注册到工厂类的注册表属性documentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getRegistry().getBeanDefinitionCount() - countBefore;}
document阅读器,将已经转成内存document的对象加载到注册表上;
//DefaultBeanDefinitionDocumentReader.java 90
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;logger.debug("Loading bean definitions");Element root = doc.getDocumentElement();doRegisterBeanDefinitions(root);}
遍历document逐个解析xml标签;
//DefaultBeanDefinitionDocumentReader.java 116
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;//创建解析DOM树对象的工具BeanDefinitionParserDelegatethis.delegate = createDelegate(getReaderContext(), root, parent);if (this.delegate.isDefaultNamespace(root)) {//如果不包含<profile>标签则略过该操作,非必要方法,略过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)) {if (logger.isInfoEnabled()) {logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());}return;}}}preProcessXml(root);//预留方法,解析前的扩展操作parseBeanDefinitions(root, this.delegate);//核心方法,解析DOM树postProcessXml(root);//预留方法,解析后的扩展操作this.delegate = parent;}
5.7 解析配置文件
解析内存的DOM文件树;
//DefaultBeanDefinitionDocumentReader.java 161
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;//包含http://www.springframework.org/schema/beans的为默认命名空间if (delegate.isDefaultNamespace(ele)) {parseDefaultElement(ele, delegate);}else {//非默认命名空间的有<mvc/>、<context/>、<aop/>等delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);}}
解析默认命名空间的标签;
//DefaultBeanDefinitionDocumentReader.java 182
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}elseif (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}elseif (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);//解析命名空间为bean的标签}elseif (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);}}
解析标签细节,新建BeanDefinition包装类,持有BeanDefinition引用,beanName和别名;
//DefaultBeanDefinitionDocumentReader.java 298
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {//将DOM树对象转化为BeanDefinition包装类bdHolderBeanDefinitionHolder 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));}}
//BeanDefinitionParserDelegate.java 427
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {return parseBeanDefinitionElement(ele, null);}
//BeanDefinitionParserDelegate.java 436
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {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);}//DOM树标签映射到BeanDefinition对象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;}
//BeanDefinitionParserDelegate.java 521
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {this.parseState.push(new BeanEntry(beanName));String className = null;if (ele.hasAttribute(CLASS_ATTRIBUTE)) {className = ele.getAttribute(CLASS_ATTRIBUTE).trim();}try {String parent = null;if (ele.hasAttribute(PARENT_ATTRIBUTE)) {parent = ele.getAttribute(PARENT_ATTRIBUTE);}//创建BeanDefinition对象,设置对应类名AbstractBeanDefinition bd = createBeanDefinition(className, parent);//将xml里面的标签一一解析到BeanDefinition对象parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));parseMetaElements(ele, bd);parseLookupOverrideSubElements(ele, bd.getMethodOverrides());parseReplacedMethodSubElements(ele, bd.getMethodOverrides());parseConstructorArgElements(ele, bd);parsePropertyElements(ele, bd);parseQualifierElements(ele, bd);bd.setResource(this.readerContext.getResource());bd.setSource(extractSource(ele));return bd;}catch (ClassNotFoundException ex) {error("Bean class [" + className + "] not found", ele, ex);}catch (NoClassDefFoundError err) {error("Class that bean class [" + className + "] depends on not found", ele, err);}catch (Throwable ex) {error("Unexpected failure during bean definition parsing", ele, ex);}finally {this.parseState.pop();}return null;}
至此我们已经成功将单个xml配置文件里面的标签属性映射到BeanDefinitionHolder对象里面,接下来是把BeanDefinition对象登记到工厂的注册表里面;
//BeanDefinitionReaderUtils.java 143
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName = definitionHolder.getBeanName();//通过beanName注册definitionHolder的BeanDefinition对象到注册表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);}}}
注册BeanDefinition对象;
//DefaultListableBeanFactory.java 793
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;//我们奋斗这么久就是为了吧xml转换为Definition然后put到beanDefinitionMapoldBeanDefinition = this.beanDefinitionMap.get(beanName);//新的xml获取出来的应该为空if (oldBeanDefinition != null) {if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +"': There is already [" + oldBeanDefinition + "] bound.");}elseif (oldBeanDefinition.getRole() < beanDefinition.getRole()) {// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTUREif (this.logger.isWarnEnabled()) {this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +"' with a framework-generated bean definition: replacing [" +oldBeanDefinition + "] with [" + beanDefinition + "]");}}elseif (!beanDefinition.equals(oldBeanDefinition)) {if (this.logger.isInfoEnabled()) {this.logger.info("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}else {if (this.logger.isDebugEnabled()) {this.logger.debug("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}this.beanDefinitionMap.put(beanName, beanDefinition);}else {//初始化的过程,应该不允许实例化if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;if (this.manualSingletonNames.contains(beanName)) {Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);updatedSingletons.remove(beanName);this.manualSingletonNames = updatedSingletons;}}}else {//最核心的一步,就是beanDefinitionMap增加beanDefinition// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);this.manualSingletonNames.remove(beanName);}this.frozenBeanDefinitionNames = null;}if (oldBeanDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}}
5.8 对象实例化
到了这一步,我们已经完整的把所有xml配置文件里面定义的对象转化到BeanFactory里面的beanDefinitionMap,但是此时IOC容器还没开始实例化这些对象,接下来就是实例化的过程。回顾一下我们分析入口的refresh()方法,里面的finishBeanFactoryInitialization(beanFactory)就是对象的实例化过程,我们重点来分析这个方法的流程。
完成对象实例化入口
// AbstractApplicationContext.java 834
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(new StringValueResolver() {@Overridepublic String resolveStringValue(String strVal) {return getEnvironment().resolvePlaceholders(strVal);}});}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.//JVM动态织入第三方模块String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.//消除临时类加载器beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.//冻结配置文件,避免重复读取beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.//实例化非懒加载对象beanFactory.preInstantiateSingletons();}
单例对象预实例化
//DefaultListableBeanFactory.java 728
public void preInstantiateSingletons() throws BeansException {if (this.logger.isDebugEnabled()) {this.logger.debug("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {//合并具有父子关系的对象RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {//通常不是工厂beanfinal FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {@Overridepublic Boolean run() {return ((SmartFactoryBean<?>) factory).isEagerInit();}}, getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}else {getBean(beanName);//进入实例化bean}}}// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {smartSingleton.afterSingletonsInstantiated();return null;}}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}}}}
实例化工厂里面定义的对象
//AbstractBeanFactory.java 196
publicObject getBean(String name) throws BeansException {returndoGetBean(name, null, null, false);}
//AbstractBeanFactory.java 235
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.//从目标MAP里面获取实例化对象,检查是否已经实例化过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 {//判断该beanName是否被实例化为prototype或者被创建中,如果是则抛异常// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {thrownew BeanCurrentlyInCreationException(beanName);}//判断bean的定义是否存在工厂里面// 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);}//激动的说时刻到来,开始准备实例化bean了try {//获取bean的定义对象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 dep : dependsOn) {//如果所要依赖的对象反过来还要依赖自己,形成了循环依赖,就抛异常,这里不允许循环依赖if (isDependent(beanName, dep)) {thrownew BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {thrownew BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}//创建单例对象// Create bean instance.if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {try {//开始创建对象return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}//同理创建prototype类型的对象,非单例,创建出来后不再维护生命周期elseif (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) {thrownew IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {@Overridepublic 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.isInstance(bean)) {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;}
//AbstractAutowireCapableBeanFactory.java 447
@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {if (logger.isDebugEnabled()) {logger.debug("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;//确保对象对应的类被加载进内存// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.//为AOP做的钩子Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}//终于到了创建对象了,还有完没完啊。。。Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}
//AbstractAutowireCapableBeanFactory.java 504
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {//从工厂bean缓存容器里面移除instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}//为空说明不是工厂bean,可以直接创建对象if (instanceWrapper == null) {//这一步是真正的创建对象,看来还没完没了啊。。。。instanceWrapper = createBeanInstance(beanName, mbd, args);}//经过漫长的过程,我们终于得到我们心心念念的bean了,坑爹。。。final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);mbd.resolvedTargetType = beanType;// Allow post-processors to modify the merged bean definition.//创建完bean后的一些特殊操作synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}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>() {@Overridepublic Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);}});}//该方法两大重头戏,上面createBeanInstance是创建对象,populateBean是初始化属性值// 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;}elseif (!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;}
真正的bean实例化动作
//AbstractAutowireCapableBeanFactory.java 1061
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()) {thrownew BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}//工厂方法实例化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);}
//AbstractAutowireCapableBeanFactory.java 1138
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>() {@Overridepublic 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) {thrownew BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);}}
//SimpleInstantiationStrategy.java 59
@Overridepublic Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.if (bd.getMethodOverrides().isEmpty()) {Constructor<?> constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {final Class<?> clazz = bd.getBeanClass();if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {@Overridepublic Constructor<?> run() throws Exception {return clazz.getDeclaredConstructor((Class[]) null);}});}else {//构造方法反射实例化constructorToUse = clazz.getDeclaredConstructor((Class[]) null);}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}return BeanUtils.instantiateClass(constructorToUse);}else {// Must generate CGLIB subclass.return instantiateWithMethodInjection(bd, beanName, owner);}}
//BeanUtils.java 138
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {Assert.notNull(ctor, "Constructor must not be null");try {ReflectionUtils.makeAccessible(ctor);//核心核心!终于重bean里面获取类,类的构造方法,然后反射new除了对象,好累。return ctor.newInstance(args);}catch (InstantiationException ex) {throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);}catch (IllegalAccessException ex) {throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);}catch (IllegalArgumentException ex) {throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);}catch (InvocationTargetException ex) {throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());}}
5.9 对象属性初始化
经过漫长漫长的过程,我们终于把配置文件里面定义的bean,千辛万苦的读取了对应的class,抽取出构造函数,然后通过反射new除了对象,但是此时的对象还是空空如也,需要我们把预设置的值初始化进去,这也是最后一步了。
//AbstractAutowireCapableBeanFactory.java 1207
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {//获取所有的属性值PropertyValues pvs = mbd.getPropertyValues();if (bw == null) {if (!pvs.isEmpty()) {thrownew 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;//出现BeanPostProcessors又是钩子,给出各种特殊操作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) {//通过name属性来装配autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {//通过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, mbd.allowCaching);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);}
到此,从阅读器读取xml配置文件,到加载到工厂的注册表,到实例化成对象,到最后的初始化对象属性,终于结束了。
六、设计模式
设计模式总体来说分为创建,组合,通信这三个过程,来规范代码之间的关系。
工厂模式 beanFactory 单例模式 single 建造者 BeanDefinitionBuilder 包装模式 AbstractAutowireCapableBeanFactory.java 504行 doCreateBean() BeanWrapper 观察者模式 ApplicationListener 策略模式 AbstractAutowireCapableBeanFactory.java 1138行,方法instantiateBean() getInstantiationStrategy() 代理模式 aop 适配器 aop 模板 Template Method jdbcTemplate
6.1 工厂模式
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类执行。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
应用:抽象Bean工厂类AbstractBeanFactory,很好的实现了该设计模式,createBean方法创建对象的过程放在具体的子类里面实现。
//AbstractBeanFactory.java 1759
/*** Create a bean instance for the given merged bean definition (and arguments).* The bean definition will already have been merged with the parent definition* in case of a child definition.* <p>All bean retrieval methods delegate to this method for actual bean creation.* @param beanName the name of the bean* @param mbd the merged bean definition for the bean* @param args explicit arguments to use for constructor or factory method invocation* @return a new instance of the bean* @throws BeanCreationException if the bean could not be created*/protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)throws BeanCreationException;
6.2 单例模式
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的。
优点: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。2、避免对资源的多重占用(比如写文件操作)。
缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
应用: spring容器读取bean定义后,根基bean是否为单例类型来实例化对象,如果存在则不再创建
//AbstractBeanFactory.java 235
// Eagerly check singleton cache for manually registered singletons.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);}....// Create bean instance.if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}
6.3 建造者模式
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
如何解决:将变与不变分离开。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
优点: 1、建造者独立,易扩展。2、便于控制细节风险。
缺点: 1、产品必须有共同点,范围有限制。2、如内部变化复杂,会有很多的建造类。
应用实例: Spring容器在构建bean的定义时需要从配置文件里面解析后登记到容器的注册表,BeanDefinitionBuilder扮演建造者的角色来设置BeanDefinition的值。
/*** Add an indexed constructor arg value. The current index is tracked internally* and all additions are at the present point.*/public BeanDefinitionBuilder addConstructorArgValue(Object value) {this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(this.constructorArgIndex++, value);return this;}/*** Add a reference to a named bean as a constructor arg.* @see #addConstructorArgValue(Object)*/public BeanDefinitionBuilder addConstructorArgReference(String beanName) {this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(this.constructorArgIndex++, new RuntimeBeanReference(beanName));return this;}/*** Add the supplied property value under the given name.*/public BeanDefinitionBuilder addPropertyValue(String name, Object value) {this.beanDefinition.getPropertyValues().add(name, value);return this;}/*** Add a reference to the specified bean name under the property specified.* @param name the name of the property to add the reference to* @param beanName the name of the bean being referenced*/public BeanDefinitionBuilder addPropertyReference(String name, String beanName) {this.beanDefinition.getPropertyValues().add(name, new RuntimeBeanReference(beanName));return this;}
6.4 装饰器模式
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。
关键代码: 1、Component 类充当抽象角色,不应该具体实现。2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。2、动态增加功能,动态撤销。
注意事项:可代替继承。
应用实例: 包装模式
AbstractAutowireCapableBeanFactory.java 504行 doCreateBean() BeanWrapper
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)throws BeanCreationException {//装饰器类,包装了具体的bean,将附带的功能封装在装饰器里面// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);mbd.resolvedTargetType = beanType;// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}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>() {@Overridepublic 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;}elseif (!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;}
6.5 观察者模式
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
关键代码:在抽象类里有一个 ArrayList 存放观察者们。
优点: 1、观察者和被观察者是抽象耦合的。2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对象是谁。
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
注意事项: 1、JAVA 中已经有了对观察者模式的支持类。2、避免循环引用。3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
应用实例: 观察者模式
ApplicationEventPublisher, ApplicationListener
//AbstractApplicationContext.java 370
protected void publishEvent(Object event, ResolvableType eventType) {Assert.notNull(event, "Event must not be null");if (logger.isTraceEnabled()) {logger.trace("Publishing event in " + getDisplayName() + ": " + event);}// Decorate event as an ApplicationEvent if necessaryApplicationEvent applicationEvent;if (event instanceof ApplicationEvent) {applicationEvent = (ApplicationEvent) event;}else {applicationEvent = new PayloadApplicationEvent<Object>(this, event);if (eventType == null) {eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();}}// Multicast right now if possible - or lazily once the multicaster is initializedif (this.earlyApplicationEvents != null) {this.earlyApplicationEvents.add(applicationEvent);}else {getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);}// Publish event via parent context as well...if (this.parent != null) {if (this.parent instanceof AbstractApplicationContext) {((AbstractApplicationContext) this.parent).publishEvent(event, eventType);}else {//发布事件,context接收到事件this.parent.publishEvent(event);}}}
6.6 策略模式
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护问题。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
优点: 1、算法可以自由切换。2、避免使用多重条件判断。3、扩展性良好。
缺点: 1、策略类会增多。2、所有策略类都需要对外暴露。
使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。2、一个系统需要动态地在几种算法中选择一种。3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
应用实例: 策略模式
AbstractAutowireCapableBeanFactory.java 1138行;方法 instantiateBean() getInstantiationStrategy()
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>() {@Overridepublic 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);}}
七、思想
IOC容器(Inversion of Control,缩写为IoC)也称为控制反转。这个词很多同学都很熟悉,但是真正要理解好并不是一件容易的事情。
控制反转是代表一种思想,依赖注释是一种实现设计模式。
控制反转是在以解耦为目标驱动而产生的一种思想,终极目标就是通过IOC容器提供中间商的作用,让对象之间的依赖不靠对象自身控制。
7.1 控制反转
汽车发动机里面的齿轮大小不一,相互咬合着转动,协同工作。这个非常复杂的一套机械系统,其中任何一个齿轮发生故障都有可能导致发动机抛锚。对比我们软件设计过程遇到的就是深耦合的问题,随着软件复杂度的日益增加,我们迫切需要解决对象之间耦合过高的情形。
软件专家Michael Mattson提出了IOC理论,也就是控制反转,它是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度。其核心思想是:借助“第三方平台”实现具有依赖关系的对象之间的解耦。
引入第三方平台后,对象的主动控制被剥夺,不再自主显式创建所要依赖的对象,而是被动的由第三方平台来控制,当执行到需要其他对象的时候,第三方平台会自动返回所需对象。这样的一种由主动创建到被动分配对象的方式,就叫做控制反转。这个第三方平台就是IOC容器,在它的眼里各个对象之间都是独立的存在,他们之间的依赖关系也只是被写到注册表里面,运行的时候回去检查依赖所需,按需分配,把对象“粘合”到容器里面。
控制反转是一种思想,不止应用在软件设计中,现实生活中其实也是可以用得到的。比如电影院提供卖票服务,每增加一个渠道电影院就得新增人员与其对接,这样如果渠道多的话电影院就忙不过来,而且很容易出错。与其这样每次新增人员对接,电影院索性制定了对接标准,你们谁要来我这里拿电影票,就得按我的标准来。电影院不再需要每次都主动对接渠道,而是把控制权拿过来,自己制定标准,渠道商按照标准来,这也是控制反转的一种实践。
7.2 依赖注入
依赖注入就是将实例变量传入到一个对象中去(Dependency injection means giving an object its instance variables)
思想实现需要具体的步骤,依赖注入就是实现控制反转的方法论。
最后容我举一个粗浅的例子,如果说spring容器的context是舞台,那么bean就是演员,spring的core就是剧本,让bean在舞台上享受了她们的人生(生命周期)。