Spring源码分析

文章目录

        • 为什么要看Spring源码
        • 如何看源码
        • Spring中的IoC容器
        • BeanFactory
        • BeanDefinition
        • Spring容器的初始化流程
          • IoC容器的使用
          • 容器初始化入口
          • 解析&注册BeanDefinition
          • BeanDefinitionReader继承结构
          • 总结一下
          • Bean的实例化&依赖注入
          • bean实力化
          • 小结
          • 循环依赖问题
        • Spring AOP原理
          • 查找BeanDefinitionReader
          • AopNamespaceHandler
          • Advice
          • AOP核心原理
          • 总结

为什么要看Spring源码

  • 解决使用框架时遇到的问题
  • 深入理解底层原理,帮助更好的使用框架
  • 深入理解面向对象思想和深入理解设计模式
  • 高级程序员的常见面试点

如何看源码

  • 确定主线,即想看那个流程的源码
  • 找到流程入口
  • 参考相关文档
  • 寻找源代码规律

Spring中的IoC容器

在Spring中,有两种主要的容器类型,一种是BeanFactory,一种是ApplicationContext。其中BeanFactory是底层的容器实现,提供了IoC容器的基础功能,而ApplicationContext是一种应用级的容器,除了基础功能外还提供了更加丰富的功能,例如:

  • 支持不同的信息源
  • 支持事件发布
  • 在ApplicationContext中提供附加服务

BeanFactory

BeanFactory是Spring中对IoC容器的核心抽象,在BeanFactory中定义了IoC容器的核心方法

Object getBean(String name) throws BeansException;
 T getBean(String name, Class requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
 T getBean(Class requiredType) throws BeansException;
 T getBean(Class requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class typeToMatch) throws NoSuchBeanDefinitionException;
Class getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);

从接口中的方法签名可以很清楚的看到,BeanFactory提供了作为容器的基本功能。

基于BeanFactory,Spring提供了一系列的子接口即实现类来丰富BeanFactory,使其成为一个强大的IoC容器。BeanFactory的主体结构如下图所示:

Spring源码乍看给人一种很复杂的感觉,但如果把主体结构抽取出来,就可以很清楚的看到它的轮廓。

从图中可以看出,接口层主要包含了四个层次,从上到下依次是一个不断丰富功能的过程。

首先是BeanFactory,这是Spring IoC容器的顶级接口,上面已经介绍过。

往下走,分别是三个平级的接口,分别是ListableBeanFactory/AutowireCapableBeanFactory/HierachialBeanFactory,这三个接口都对BeanFactory进行了扩展。从名称可以比较明显的看出这几个接口扩展的方面。

ListableBeanFactory

boolean containsBeanDefinition(String beanName);
int getBeanDefinitionCount();
String[] getBeanDefinitionNames();
String[] getBeanNamesForType(ResolvableType type);
String[] getBeanNamesForType(Class type);
String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit);
 Map getBeansOfType(Class type) throws BeansException;
 Map getBeansOfType(Class type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException;
String[] getBeanNamesForAnnotation(Class annotationType);
Map getBeansWithAnnotation(Class annotationType) throws BeansException;
 A findAnnotationOnBean(String beanName, Class annotationType)
			throws NoSuchBeanDefinitionException;

从接口签名中可以看出,ListablebeanFactory提供了Bean枚举相关的功能,如获取所有bean的名称及bean的总数量,获取bean名称和bean的映射等。

第二个接口是AutowireCapableBeanFactory,这个接口在BeanFactory的基础上扩展了自动装配的功能,例如创建Bean/自动配置bean/解析依赖以及与bean生命周期相关的功能。

代码略。

第三个接口是HieracicalBeanFactory,这个接口同样扩展子BeanFactory,它提供了在容器存在父子关系场景下与容器继承相关的操作。例如WebApplicationContext及ApplicationContext。

代码略。

至此,第二层继承接口就完事了。下面就是ConfigurablebeanFactory这个接口,这个接口继承自HieracicalBeanFactory,同时又扩展了SingletonBeanFactory,也就是与单例模式的Bean注册相关的功能,之所以这么做,个人理解单例模式是bean最常见的形式,将其注册能力加到稍顶级的接口中,有利于规范下层实现的行为。

代码略。

ConfigurableListableBeanFactory是第三层接口,这个接口同时继承了ListableBeanFactory,AutowrieCapablebeanFactoryConfigurableBeanFactory这三个接口,可以把它理解为spring中常用容器的顶级接口,它定义了一个功能完善的IoC容器的几乎所有行为。

代码略。

至此,BeanFactory体系的主体框架就看完了。

BeanDefinition

BeanDefinition是spring中对bean及bean依赖关系的抽象,如果把spring比做一个制造并管理bean的工厂的话,那BeanDefinition就是创造bean的原材料。

在spring启动过程中,spring会解析配置文件或配置类,将对应的bean定义解析成BeanDefinition并注册到spring容器中,在后续,spring会根据这些具体的BeanDefinition对象来创建并初始化这些bean。

BeanDefinition的继承结构如下:

Spring容器的初始化流程

由于我们在日常开发中经常使用的IoC容器是ApplicationContext,而不是更加底层的BeanFactory,所以在分析Spring容器初始化时,就以ApplicationContext为例,下面是ApplicationContext的体系结构

IoC容器的使用

由于在日常开发中,最常见的是ClassPathXmlApplicationContext,所以就以此为例来分析。首先看一下在日常开发中基本的使用方式。


	contextConfigLocation
	classpath:spring.xml


	
        org.springframework.web.context.ContextLoaderListener
    


ApplicationContext ctx = new ClasspPthXmlApplicationContext("spring.xml");
容器初始化入口

ClassPathXmlApplicationContext.java

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

AbstractApplicationContext.java

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			//Step1: 刷新预处理
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//Step2:创建IoC容器,解析xml,注册BeanDefinition
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//Step3:对IoC容器进行预处理
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//Step4:
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//Step5:调用BeanFactoryPostProcessor后置处理器对BeanDefinition进行处理
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				
				//Step6:注册BeanPostProcessor
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				//Step7:初始化消息源(国际化)
				initMessageSource();

				// Initialize event multicaster for this context.
				//Step8:初始化应用事件广播
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				//Step9:初始化一些特殊的bean
				onRefresh();

				// Check for listener beans and register them.
				//Step10:注册监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//Step11:实例话单例Bean,Bean的依赖注入和AOP都发生在这一步
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//Step12:完成,发布事件
				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();
			}
		}
	}

在分析源码前,要先明确一下spring容器初始化的核心流程:

  1. 创建容器
  2. 加载配置资源文件
  3. 解析并注册BeanDefinition
  4. 完成bean的创建与初始化

这四个步骤对应到上面的refresh方法中,其中前三步是在step2中完成,第四步主要是在step11中完成。

解析&注册BeanDefinition
1.AbstractApplicationContext.java
/**
    a)创建IoC容器
    b)加载xml文件
    c)解析并生成BeanDefinition,并注册到容器中
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

2.AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        /**
            a)销毁存在的容器
            b)创建BeanFactory
            c)加载资源文件,并向容器中注册BeanDefinition
        */
		refreshBeanFactory();
		/**
		    返回上一步创建的BeanFactory
		*/
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

3.AbstractRefreshableApplicationContext.java
protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
		    /**
		      创建BeanFactory,这一步直接通过new创建来一个DefaultListableBeanFactory
		      
		      new DefaultListableBeanFactory(getInternalParentBeanFactory());
		    */
			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);
		}
	}


4.AbstractXmlApplicationContext.java
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		
		/**
		   初始化BeanDefinitionReader来完成文件都读取和
		   加载BeanDefinition。
		*/
		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));
		
		initBeanDefinitionReader(beanDefinitionReader);
		
		/**
		   加载BeanDefinition,由子类完成。
		   
		   protected Resource[] getConfigResources() {
		return null;
	}
		*/
		loadBeanDefinitions(beanDefinitionReader);
	}
	
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        /**
            由子类完成:ClassPathXmlApplicationContext
            protected Resource[] getConfigResources() ;
        */
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

	
5.ClassPathXmlApplicationContext.java
//初始化Resource是在创建具体的ClassPathXmlApplicationContext时进行的。
public ClassPathXmlApplicationContext(String[] paths, Class clazz, ApplicationContext parent)
			throws BeansException {

		super(parent);
		Assert.notNull(paths, "Path array must not be null");
		Assert.notNull(clazz, "Class argument must not be null");
		this.configResources = new Resource[paths.length];
		for (int i = 0; i < paths.length; i++) {
			this.configResources[i] = new ClassPathResource(paths[i], clazz);
		}
		refresh();
	}
@Override
protected Resource[] getConfigResources() {
	return this.configResources;
}

6.AbstractBeanDefinitionReader.java
public int loadBeanDefinitions(String location, Set actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				/**
				 此处时核心调用逻辑,最终会进入到具体实现类
				 XmlBeanDefinitionReader中进行处理
				*/
				int loadCount = loadBeanDefinitions(resources);
				if (actualResources != null) {
					for (Resource resource : resources) {
						actualResources.add(resource);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
				}
				return loadCount;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// Can only load single resources by absolute URL.
			Resource resource = resourceLoader.getResource(location);
			int loadCount = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
			}
			return loadCount;
		}
	}
	
7.XmlBeanDefinitionReader.java 
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
	
		try {
		    
		    /**
		      此处调用的getResource是由具体的ApplicationContext
		      提供的。
		    */
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				/**
				  最终执行加载xml/解析BeanDefinition并进行注册的
				  核心方法。
				*/
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
	}

8.XmlBeanDefinitionReader.java
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){
    /**
      BeanDefinitionReader这个组件的主要作用就是将xml解析成
      Document对象,然后它就会将任务转交给BeanDefinitionDocumentReader
    */
    Document doc = doLoadDocument(inputSource, resource);
	return registerBeanDefinitions(doc, resource);
}

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
}


9.上接getResource
getResoruce()方法的作用是加载配置信息对应的Resource流对象,这个方法被定义在ResourceLoader接口中
public interface ResourceLoader {
    String CLASSPATH_URL_PREFIX = "classpath:";
    Resource getResource(String var1);
    ClassLoader getClassLoader();
}

而ApplicationContext的顶级父类AbstractApplicationContext继承了DefaultResourceLoader(),子类ApplicationContext可以同覆盖getResource()来实现自己的加载配置信息的方式。



10.XmlBeanDocumentReader.java
BeanDefinitionReader会将解析&注册任务交给BeanDefinitionDocumentReader来完成

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        // 创建DocumentReader
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		// 将任务转交给DocumentReader
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
}

11.DefaultBeanDefinitionDocumentReader.java
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else {
					    //解析默认名称空间
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
		     //解析其他名称空间
			delegate.parseCustomElement(root);
		}
	}
这里涉及到一个重要的操作,就是确定NamespaceHandler,在parseCustomElement方法中主要来处理
import/bean/beans等spring的核心标签,在parseCustomElement方法中主要来处理aop/context/mvc
等其他名称空间中的标签。

在处理其他名称空间的标签时,需要首先找到对应的NamespaceHandler,这个过程是通过加载classpath
下的spring.handler文件完成的,在spring.hander文件中定义了每一种名称空间对应的NameSpaceHandler


12.BeanDefinitionParserDelegate.java
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		/**
		 这一步就是从spring.handler中寻找对应的NamespaceHandler
		*/
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}
BeanDefinitionReader继承结构

BeanDefinitionReader的主要作用是读取外部资源文件,解析成BeanDefintion

BeanDefinitionReader
  AbstractBeanDefinitionReader
    GroovyBeanDefinitionReader
    XmlBeanDefinitionReader
    PropertiesBeanDefinitionReader
总结一下
  • spring容器的启动入口是refresh()方法,在refresh()方法中定义了spring IoC容器初始化的骨架,为Bean的生命周期管理提供了条件;
  • 默认的IoC Bean工厂是DefaultListableBeanFactory;
  • BeanDefinition是spring中对Bean对象及其依赖关系的抽象;
  • ApplicationContext通过实现ResourceLoader接口实现加载Bean定义信息的具体方式;
  • BeanDefinitionReader负责从Resource中解析BeanDefinition,并将BeanDefintion注册到IoC 容器中;
  • BeanDefinitionReader注册BeanDefinition是通过BeanFactory实现的BeanDefinitionRegistry接口提供的相关能力实现的;
  • ApplicationContext是一个持有BeanFactory的/功能被强化了的IoC容器
  • 最终被解析出来的BeanDefinition被注册到了BeanFactory的HashMap中;
  • BeanDefinitionReader的主要任务是将xml解析成Document,然后它就会将具体的解析和注册BeanDefinition的任务交给BeanDefinitionDocumentReader;
  • 对于不同的名称空间中的标签,是通过在spring.handler中定义其对应关系来指定对应的NamespaceHandler的;
Bean的实例化&依赖注入
bean实力化

在IoC容器顶级接口BeanFactory中声明了getBean()的一些列重载方法,Bean的实例化和依赖注入都是从这里开始是(lazy-init=false除外),下面我们从AbstractBeanFactory中都getBean开始入手,来看一下Spring bean的实例化过程。

@Override                                                                     
public Object getBean(String name) throws BeansException {                    
	return doGetBean(name, null, null, false);                                
}                                                                             
//这里定义了bean初始化和依赖入住的最顶层逻辑
protected  T doGetBean(
			final String name, final Class 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 + "'");
				}
			}
			
			//此处,处理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.
			
			//此处处理具有继承关系的容器体系,利用递归顺着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);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						getBean(dep);
					}
				}

				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory() {
						@Override
						public Object getObject() throws BeansException {
							try {
							   
							    /**
							        此处进入创建bean的核心逻辑
							    */
								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 name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory() {
							@Override
							public Object getObject() throws BeansException {
							    // 更新bean 的创建状态
								beforePrototypeCreation(beanName);
								try {
								    //进入创建bean的核心逻辑
									return createBean(beanName, mbd, args);
								}
								finally {
								    // 更新创建bean的状态
									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;
	}
 
  

从上面的代码中我们可以看出,doGetBean中会继续调用createBean()方法来完成bean的创建,那么我们就来分析一下createBean()这个方法


AbstractBeanFactory.java:
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
		throws BeanCreationException;                                                       


AbstractAutowireCapableBeanFactory.java

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			
			//此处处理实现来BeanPostProcessor 的Bean,会返回一个代理对象
			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);
		}

        /**
            下面进入正在创建bean对象的doCreateBean()方法中
        */
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	
/**
 
*/	
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
		
		    //step1: 创建实例对象
			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() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
		    //step2: 填充属性
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
			    // step3:调用init方法
				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 actualDependentBeans = new LinkedHashSet(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的主体过程

  1. 判断bean 类型(bean or factorybean)和scope类型
  2. 为实现来BeanPostProcessor的bean创建代理对象
  3. 利用构造函数/反射创建bean对象(createBeanInstance)
  4. 填充属性(populateBean)
  5. 调用init初始化方法
循环依赖问题

在进行依赖注入是, 如果bean A依赖于bean B,那么在初始化A的时候,会先去初始化B。那么,如果A依赖于B,同时B由依赖于A怎么办呢?

依赖的类型有两种,一种是构造启依赖,一种的属性setter依赖,那么就可以把循环依赖分为以下几种:

  1. A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象
  2. A的构造方法中依赖了B的实例对象,同时B的某个field或者setter需要A的实例对象,以及反之
  3. A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象,以及反之

对于第1种情况,是没办法解决的,因为没办法把创建对象和设置属性值用一步完成。

Spring是通过三个级别的缓存来解决循环依赖问题的,解决思路简单的说就是将创建对象和设置属性分开进行。

这三个缓存分别是:

/** Cache of singleton objects: bean name --> bean instance */
private final Map singletonObjects = new ConcurrentHashMap(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map> singletonFactories = new HashMap>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map earlySingletonObjects = new HashMap(16);

下面再看一下下面的代码段:

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() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}
 
  

首先解释一下上面说的三个缓存:

singletonObjects:存放创建好的单例对象

singletonFactories:存放用于创建某个单例bean的工厂对象,该工厂从earlySingletonObjects中得到对象

earlySingletonObjects:存放被提前曝光的单例bean对象

下面以一个例子来说明处理流程:
a依赖于b,b依赖于a,前提是setter依赖,处理过程大致如下:

  1. getBean(b);
  2. 利用b的构造函数创建b对象,并将其放入earlySingletonObjects中,发现其依赖于a,则更新b状态为正在创建
  3. 转而去利用a创建a的实例对象,发现a对象依赖于b
  4. 首先,查找singletonObjects,若没有,查找singletonFactories,找到对应的Factory
  5. 该factory会从earlySingletonObjects中找到被提前曝光的a
  6. 虽然此时a并不完整,因为b属性还没注入,单此时,b对象可以注入a
  7. 此时b创建完成,b被放入singletonObjects中
  8. 创建a的步骤继续往下走,尝试从singletonObjects中获取b
  9. 因为b已经创建完成,所以获取b对象成功,然后继续注入a的b属性
  10. a创建完成,a被放入singletonObjects中
  11. 循环依赖bean创建结束

Spring AOP原理

分析aop原理要从下面三个方面入手:

  • 如果根据标签查找对应的BeanDefinitionParser
  • BeanDefinitionParser的解析流程
  • 产生apo代理的流程(何时/如何产生代理)
查找BeanDefinitionReader

回顾BeanDefinition的解析过程:

BeanDefinitionReader->BeanDefinitionDocumentReader(DefaultBeanDefinitionDocumentReader)->BeanDefinitionParserDelegate->.parseCustomElement()

//在该方法中通过具体的NameSpaceHandler来解析xml
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

查找NamespaceHandler是通过查找classpath下的spring.handler来实现的,在spring.handler中定义了名称空间和具体的NamespaceHandler之间的关系

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

AopNamespaceHandler
public interface NamespaceHandler {
    void init();
    BeanDefinition parse(Element element, ParserContext parserContext);
    BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
}

public class AopNamespaceHandler extends NamespaceHandlerSupport {
    public AopNamespaceHandler() {
    }

    public void init() {
        this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
        this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }
}

以上就是AopNamespaceHandler的全貌,可以清楚的看到最常用的两个标签对应的前缀



    
    
        
    

而解析动作是在BeanDefinitionParserDelegate的parseCustomElement()方法中开始的

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		//次数就是调用NamespaceHandler中的parse方法
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

紧接着,就进入到AopNamespaceHandler中到parse()方法中,最终通过具体的BeanDefinitionParser来解析xml标签,先来看一下ConfigBeanDefinitionParser

public BeanDefinition parse(Element element, ParserContext parserContext) {
        CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
        parserContext.pushContainingComponent(compositeDef);
        
        //创建一个用于创建代理对象的ProxyFactory
        this.configureAutoProxyCreator(parserContext, element);
        List childElts = DomUtils.getChildElements(element);
        Iterator var5 = childElts.iterator();

        while(var5.hasNext()) {
            Element elt = (Element)var5.next();
            String localName = parserContext.getDelegate().getLocalName(elt);
            //解析
            if ("pointcut".equals(localName)) {
                this.parsePointcut(elt, parserContext);
                //解析
            } else if ("advisor".equals(localName)) {
                this.parseAdvisor(elt, parserContext);
                //解析
            } else if ("aspect".equals(localName)) {
                this.parseAspect(elt, parserContext);
            }
        }

        parserContext.popAndRegisterContainingComponent();
        return null;
    }
    

切入点 + 切面 + 目标类 + ProxyFactory = 代理对象

Advice

解析每个标签是会产生一个BeanDefinition,pointcut对应的是AspectJExpressionPointcut,advicer对应的是DefaultBeanFactoryPointcutAdvisor,aspect对应的是AspectComponentDefinition,advice对应的是AspectJMethodBeforeAdvice/AspectJAfterAdvice/AspectJAfterReturningAdvice/AspectJAfterThrowingAdvice/AspectJAroundAdvice,解析标签的过程就是创建这些类对应的对象的过程,然后会将对应的BeanDefinition注册到Spring容器中。

所有类都实现类Advice接口,这是AOP联盟都规定。

AOP核心原理

从上面都源码中可以看到,AopNamespaceHandler中都parse方法主要做了两件事情:

  • 向容器中注册AspectJAwareAdvisorAutoProxyCreator
  • 解析xml,生成BeanDefinition并注册到spring容器中

其中,AspectJAwareAdvisorAutoProxyCreator的主要作用是在初始化bean的时候被调用,根据parse()方法解析出来的BeanDefinition来创建代理对象。

下面看一下生成代理类的核心逻辑。

由于Spring的在第一次获取bean的时候创建对象的(lazy-init=false除外),所以入口就是AbstractBeanFactory的getBean(Class type)方法,最终调用链进入到AbstractAutowiredCapableBeanFactorydoCreateBean()方法中

try {
	populateBean(beanName, mbd, instanceWrapper);
	if (exposedObject != null) {
			exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
}
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(new PrivilegedAction() {
				@Override
				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()) {
		    /**
		      此处就会处理所有实现类BeanPostProcessor接口的Bean,
		      由于AspectJAwareAdvisorAutoProxyCreator实现了
		      BeanPostProcessor接口,所以此处就会调用postProcessAfterInitialization方法
		    */
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}
	
	
public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }


/**
    AbstractAutoProxyCreator的postProcessAfterInitialization()方法
    是创建代理对象的核心入口
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }

        return bean;
    }
 
  

接下来就进入到wrapIfNessary(bean,beanName,cachekey)方法中

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
            /**
                根据Bean获取与其关联的所有Advisor
            */
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                //生成代理对象
                Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }

经过层层调用,最终进入到了DefaultAopProxyFactory的createAopProxy()方法中

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            Class targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
}

代码已经看的非常清晰了,spring提供了两种代理实现:JDK动态代理和Cglib字节码代理。

总结

总结一下aop的核心实现思路:

  • referer()方法被调用时,通过spring.handler定义到具体的NamespaceHandler,并调用init方法注册具体的Parser,然后有Parser解析不同类型的标签
  • 解析时,将pointcut/advisor/aspect分别解析成对应的PointCut和Advice类,并注册到Spring容器中
  • 调用BeanFactory的getBean()时,触发bean的初始化
  • 由于解析时,向容器中注册了一个用于创建代理对象的ProxyCreator,并且这个Creator实现了BeanPostProcessor,所以,由于在初始化时,spring会统一处理BeanPostProcessor,所以ProxyCreator的after方法被调用
  • 在ProxyCreator的after方法中获取当前bean对应的advice
  • 然后调用ProxyFactory(DefaultAopProxyFactory)的createProxy()方法
  • createProxy()方法根据是否实现了接口来选择采用JDK动态代理或Cglib静态代理来生成代理对象
  • 最终用户调用到的对象就是被织入来切面的代理对象

你可能感兴趣的:(Code-Spring)