源码分析

目录

分析源码 

Spring源码分析 

IOC体系

BeanFactory (1)

BeanDefinition(2) -做xml解析,封装了spirngbean文件

Bean的解析方式

Bean生命周期分析

SpringAop源码分析 -解决重复代码 

AbstractAutoProxyCreator类(3)

SpringMVC执行流程


分析源码 

源码分析_第1张图片

源码分析_第2张图片

Spring源码分析 

BeanFactory

         Spring Bean的创建是典型的工厂模式,这一系列的Bean工厂,也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在Spring中有许多的IOC容器的实现供用户选择和使用,其相互关系如下:

源码分析_第3张图片

IOC体系

BeanFactory (1)

 BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是Spring IOC 所遵守的最底层和最基本的编程规范。在  Spring 代码中, BeanFactory 只是个接口,并不是 IOC容器的具体实现,但是 Spring 容器给出了很多种实现,如 DefaultListableBeanFactory  XmlBeanFactory ApplicationContext 等,都是附加了某种功能的实现。

public interface BeanFactory {
	//这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,  
  //如果需要得到工厂本身,需要转义    
    //转义符“&”用来获取FactoryBean本身
	String FACTORY_BEAN_PREFIX = "&";
//根据bean的名字进行获取bean的实例,这是IOC最大的抽象方法
	Object getBean(String name) throws BeansException;
//根据bean的名字和Class类型进行获取Bean的实例,和上面方法不同的是,bean名字和Bean 的class类型不同时候会爆出异常
	 T getBean(String name, Class requiredType) throws BeansException;
	 T getBean(Class requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
//检测这个IOC容器中是否含有这个Bean
boolean containsBean(String name);
//判断这个Bean是不是单利

	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//判断这个Bean是不是原型
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//查询指定的bean的名字和Class类型是不是指定的Class类型
	boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
//这里对得到bean实例的Class类型
	Class getType(String name) throws NoSuchBeanDefinitionException;
//这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来 
	String[] getAliases(String name);
}

BeanDefinition(2) -做xml解析,封装了spirngbean文件

这个接口,可以理解为xml bean元素的数据载体。通过对比xml bean标签的属性列表和BeanDefinition的属性列表一看便知。

我的理解,是解析XML的过程,就是 xml 元素内容 转换为BeanDefinition对象的过程。而且这个接口,支持层级,对应对象的继承。

有一个类BeanDefinitionHolder,BeanDefinitionHolder,根据名称或者别名持有beanDefinition,它承载了nameBeanDefinition的映射信息。

BeanWarpper:

提供对标准javabean的分析和操作方法:单个或者批量获取和设置属性值,获取属性描述符,查询属性的可读性和可写性等。支持属性的嵌套设置,深度没有限制。

AbstractRefreshableApplicationContextrefreshBeanFactory()这个方法

	@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
                   //创建IOC容器工程
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
                   //加载配置文件
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

 

//加载配置文件
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();//创建IOC容器
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);//载入loadBeanDefinitions
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {  实现
/**
	 * Loads the bean definitions via an XmlBeanDefinitionReader.
	 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
	 * @see #initBeanDefinitionReader
	 * @see #loadBeanDefinitions
	 */
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}
先调用本类里面的loadBeanDefinitions
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

委托给reader.loadBeanDefinitions(configLocation);    XmlBeanDefinitionReader
通过XmlBeanDefinitionReader来读取。下面看一下XmlBeanDefinitionReader这个方法,但其实并不在这个类实现这个方法,而是在它的基类里面AbstractBeanDefinitionReader
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int counter = 0;
		for (String location : locations) {
			counter += loadBeanDefinitions(location);
		}
		return counter;
	}
进入到loadBeanDefinitions
	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();//获取IO
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());//这个方法从流中读取
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}
进入到doLoadBeanDefinitions  Resource IO封装
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			int validationMode = getValidationModeForResource(resource);
			Document doc = this.documentLoader.loadDocument(
					inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
			return registerBeanDefinitions(doc, resource); //解析XML
		}
		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);
		}
	}
进入到registerBeanDefinitions	
/**
	 * Register the bean definitions contained in the given DOM document.
	 * Called by loadBeanDefinitions.
	 * 

Creates a new instance of the parser class and invokes * registerBeanDefinitions on it. * @param doc the DOM document * @param resource the resource descriptor (for context information) * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of parsing errors * @see #loadBeanDefinitions * @see #setDocumentReaderClass * @see BeanDefinitionDocumentReader#registerBeanDefinitions */ public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // Read document based on new BeanDefinitionDocumentReader SPI. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } documentReader.registerBeanDefinitionsXML解析 /** * Parses bean definitions according to the "spring-beans" DTD. *

Opens a DOM Document; then initializes the default settings * specified at <beans> level; then parses * the contained bean definitions. */ public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); BeanDefinitionParserDelegate delegate = createHelper(readerContext, root); preProcessXml(root); parseBeanDefinitions(root, delegate); postProcessXml(root); } -----遍历节点 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); } } ---判断解析类 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele);//import类型 } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele);//别名方式 } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate);//bean解析方式 } }

Bean的解析方式

进入到     AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);   使用反射初始化类

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);
			}
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			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;
	}
进入到AbstractBeanDefinition bd = createBeanDefinition(className, parent);
protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
			throws ClassNotFoundException {

		return BeanDefinitionReaderUtils.createBeanDefinition(
				parentName, className, this.readerContext.getBeanClassLoader());
	}
进入到BeanDefinitionReaderUtils.createBeanDefinition 
public static AbstractBeanDefinition createBeanDefinition(
			String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {

		GenericBeanDefinition bd = new GenericBeanDefinition();
		bd.setParentName(parentName);
		if (className != null) {
			if (classLoader != null) {
				bd.setBeanClass(ClassUtils.forName(className, classLoader));//使用java反射机制初始化
			}
			else {
				bd.setBeanClassName(className);
			}
		}
		return bd;
	}

Bean生命周期分析

源码分析_第4张图片

源码分析_第5张图片

 

源码分析_第6张图片

  1. spring对bean进行实例化,默认bean是单例
    2)spring对bean进行依赖注入
    3)如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法
    4)如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来
    5)如果bean实现了ApplicationContextAware()接口,spring将调用setApplicationContext()方法将应用上下文的引用传入
    6) 如果bean实现了BeanPostProcessor接口,spring将调用它们的postProcessBeforeInitialization接口方法
    7) 如果bean实现了InitializingBean接口,spring将调用它们的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,改方法也会被调用
    8)如果bean实现了BeanPostProcessor接口,spring将调用它们的postProcessAfterInitialization接口方法
    9)此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁
    10)若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用
2)	public class UserEntity
3)			implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean, ApplicationContextAware {
4)	
5)		private String userName;
6)		private Integer age = null;
7)	
8)		public UserEntity() {
9)			System.out.println("无惨构造函数.....");
10)		}
11)	
12)		public UserEntity(String userName, Integer age) {
13)			System.out.println("我是有参构造函数 userName:" + userName + ",age:" + age);
14)			this.userName = userName;
15)			this.age = age;
16)		}
17)	
18)		public String getUserName() {
19)	
20)			return userName;
21)		}
22)	
23)		public void setUserName(String userName) {
24)	
25)			this.userName = userName;
26)		}
27)	
28)		public Integer getAge() {
29)	
30)			return age;
31)		}
32)	
33)		public void setAge(Integer age) {
34)	
35)			this.age = age;
36)		}
37)	
38)		@Override
39)		public String toString() {
40)			return "UserEntity [userName=" + userName + ", age=" + age + "]";
41)		}
42)	
43)		// bean容器销毁
44)		public void destroy() throws Exception {
45)			System.out.println("destroy() 销毁bean");
46)	
47)		}
48)	
49)		// afterPropertiesSet方法,初始化bean的时候执行,可以针对某个具体的bean进行配置
50)		public void afterPropertiesSet() throws Exception {
51)			System.out.println("afterPropertiesSet");
52)		}
53)	
54)		// 如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法
55)		public void setBeanName(String name) {
56)			System.out.println("setBeanName() set name:" + name);
57)		}
58)	
59)		// 如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法
60)		public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
61)			System.out.println("setBeanFactory()");
62)		}
63)	
64)		// 获取Spring容器上下文
65)		public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
66)			System.out.println("获取上下文....");
67)	
68)		}
69)	
70)	}
71)	---------------72)	
System.out.println("开始初始化容器....");
		ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
		System.out.println("容器初始化成功....");
		UserEntity userEntity = (UserEntity) app.getBean("userEntity01");
		System.out.println("关闭容器...");
		 app.registerShutdownHook();

SpringAop源码分析 -解决重复代码 

AbstractAutoProxyCreator类(3)

spring 容器启动,每个bean的实例化之前都会先经过AbstractAutoProxyCreator类的postProcessAfterInitialization()这个方法,然后接下来是调用wrapIfNecessary方法。

源码分析_第7张图片

源码分析_第8张图片

 

SpringMVC执行流程

 

源码分析_第9张图片

源码分析_第10张图片

Spring工作流程描述

      1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;

      2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

      3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法

       4.  提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

      HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息

      数据转换:对请求消息进行数据转换。如String转换成Integer、Double等

      数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等

      数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

      5.  Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;

      6.  根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;

      7. ViewResolver 结合Model和View,来渲染视图

      8. 将渲染结果返回给客户端。


 

Spring工作流程描述

    为什么Spring只使用一个Servlet(DispatcherServlet)来处理所有请求?

     详细见J2EE设计模式-前端控制模式

    Spring为什么要结合使用HandlerMapping以及HandlerAdapter来处理Handler?

    符合面向对象中的单一职责原则,代码架构清晰,便于维护,最重要的是代码可复用性高。如HandlerAdapter可能会被用于处理多种Handler。

 

 

源码分析_第11张图片

源码分析_第12张图片

每个hander代表路径

源码分析_第13张图片

 

源码分析_第14张图片

 

源码分析_第15张图片

 

源码分析_第16张图片

 

 

 

 

你可能感兴趣的:(技术烩菜)