spring源码分析(二)

本篇文章接着上篇:spring源码分析(一) 继续分析剩下的部分。

为了观看方便,这里就再次贴上总图:
在这里插入图片描述

AOP部分

AOP入口

这一小节,简单的说了AOP是在哪里创建代理对象的以及要使用哪种方式来创建代理对象。入口方法(wrapIfNecessary)就是在bean初始化后调用的后置处理器(ProxyProcessorSupport)中执行的。这里对这个方法的执行进行了简单的分析。

筛选合适的通知器

这一小节属于第一小节中的一部分,用于获取我们写的通知方法。比如:before、after、after throwing、after returning之类的。这也是对代理对象进行增强的过程,会将增强后的对象变为Advisor类型。

创建代理对象

根据上一步返回的所有Advisor集合来创建代理对象,在创建代理对象时需要判断使用哪种方式来创建代理对象。这个过程比较简单就没有分析执行流程。创建代理对象之后,进行缓存,然后返回给spring容器。

拦截器链执行

我们从spring中获取到代理对象执行方法时,会被代理对象的intercept 方法拦截,在这行目标方法前会获取到拦截器链,遍历执行它的通知方法。思维导图中以JDK代理对象来分析执行流程的,CGLIB模式的大家可以自己分析。

AOP注解模式

现在SpringBoot越来越成为主流,导致实用注解开发也变的更加多,所以这里简单分析一些Spring开启AOP注解 @EnableAspectJAutoProxy 。下面是分析这个注解的过程。这里面有一些其他的东西,望大家见谅。

AOP 注解模式中,需要使用@EnableAspectJAutoProxy 注解表示开启切面支持
@EnableAspectJAutoProxy 注解中导入了AspectJAutoProxyRegistrar类
	这个类实现 ImportBeanDefinitionRegistrar 接口,这个接口表示可以给spring容器导入一些BeanDefinition,可以重写其registerBeanDefinitions方法
	重点查看其 registerBeanDefinitions方法
	
	这个类向spring中注册了 key=下面,value=AnnotationAwareAspectJAutoProxyCreator 的类
	org.springframework.aop.config.internalAutoProxyCreator
	
接下来分析 AnnotationAwareAspectJAutoProxyCreator 这个类有什么功能
	extends AspectJAwareAdvisorAutoProxyCreator 
		extends AbstractAdvisorAutoProxyCreator 
			extends AbstractAutoProxyCreator 
				extends ProxyProcessorSupport
				implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware 
				
有后置处理器的特性,还有Aware的特点

	postProcessBeforeInstantiation  	InstantiationAwareBeanPostProcessor 接口 
	postProcessBeforeInitialization  	这两个。。。。 一个实例化,一个初始化
	
	
	BeanPostProcessor 接口 有的两个方法是:Initialization 初始化
	
	
	AnnotationAwareAspectJAutoProxyCreator 类 实现了后置处理器和beanFactoryAware接口 
		在加载配置文件时,refush时,会有一步注册beanPosscessors,所以就会加载这个
			initializeBean --> invokeAwareMethods   先调用XXXAware 的接口实现类的方法获取spring的组件放到自己的组件中 
		refush时,有一步实例化单实例对象的过程,
			createBean  
				resloveBeforeInstantion (这是是AnnotationAwareAspectJAutoProxyCreator 类一个父接口拓展BeanFactory接口的方法)
			-- > doCreateBean
				populateBean -->  postProcessAfterInstantiation  和 postProcessPropertyValues   这是bean初始化前后的后置处理器执行
				initializeBean -->  applyBeanPostProcessorsBeforeInitialization 
				
				createBeanInstance (创建bean实例)
				0、在创建bean实例前,会执行resolveBeforeInstantion,如果是InstantiationAwareBeanPostProcessor接口的。实例化的前置处理
					这个会拦截所有单实例bean的创建,
				1、先createBeanInstance,创建bean实例
				2、在populateBean时,会执行实例化的后置处理、实例化的赋值前的后置处理
				3、填充属性完后,会有调用Aware接口、初始化操作执行,会有初始化前后的后置处理操作。
				
	postProcessBeforeInstantiation 
		isInfrastructureClass方法 
			super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass)
			判断是否为基础类(Advice、Pointcut、Advisor、AopInfrastructionBean)
			判断是否为切面 
		shouldSkip方法
		
		
	在创建aop代理对象的时候,会对aop对象的通知进行增强,转为Advisor类型,在代理对象执行时又会将增强器转为MethodIntercepter拦截器
	aop拦截器链,MethodInterceter拦截器  将增强器转为MethodInterceter 拦截器
	什么时候执行aop的拦截方法?
		CglibMethodInvocation.proceed方法
			先拦截before、after、afterReturning、
			ExposeU=InvocationInterceper 

MVC部分

这个部分为两个小节。

前期准备

在分析代码之前需要先了解DispatcherServlet的一些继承关系,然后知道每个类或接口都是干什么的。然后又简单的说了一下SpringMVC的执行流程。

容器创建

这一小节,先简单对容器的分类做了一些说明,然后就分析容器的创建过程。

这一部分的内容比较少,所以就再贴一下SpringMVC的整体执行流程分析。

————————————————————————————————servlet容器启动时————————————————————————————————
1、 web容器在启动的时候,会扫描每个jar包下的 META-INF/services/javax.servlet.ServletContainerInitializer 文件
	会加载这个文件中写的类。这个类继承了 servlt 规范中的 ServletContainerInitializer 接口。
2、 在spring中就是 org.springframework.web.SpringServletContainerInitializer 这个类。
	该类上有注解: @HandlesTypes(WebApplicationInitializer.class) ,会在servlet容器启动是自动获取 WebApplicationInitializer 的子类,
	并将子类封装为一个集合,传递给实现 ServletContainerInitializer 接口的 onStartup 方法。
3、 SpringServletContainerInitializer 的 onStartup 方法
	1、 遍历 WebApplicationInitializer 子类集合创建对象,然后放到一个对象集合中。
	2、 排序对象集合后,遍历对象集合。分别调用其 onStartup 方法。
		1、 super.onStartup(servletContext); 调用父类的方法
			1、 registerContextLoaderListener(servletContext); 注册 ContextLoaderListener ,当servlet容器被加载完成后会被监听器感知
				1、 createRootApplicationContext(); 创建一个 业务 容器。类型是 AnnotationConfigWebApplicationContext 的。
				2、 如果创建的业务容器不为空,执行如下操作
					1、 创建一个监听器( ContextLoaderListener  ),绑定刚才创建好的 WebApplicationContext 。 
					2、 设置servlet容器的初始化操作。
					3、 在servlet容器中注册这个监听器。
		2、 registerDispatcherServlet(servletContext); 注册DispatcherServlet
			1、 获取servletname
			2、 创建 ServletApplicationContext ,也就是 web 容器。类型是 AnnotationConfigWebApplicationContext 的。
			3、 根据创建出来的web容器创建 DispatcherServlet 。
			4、 将创建出来的 DispatcherServlet 注册到 ServletContext 中,并执行设置mapping之类的操作。
			5、 获取所有的ServletFilter,遍历注册之
			6、 执行用户自定义注册。customizeRegistration(registration); 该方法默认什么都不做,可以被子类覆盖。
	
————————————————————————————————servlet容器创建后,创建 业务 容器————————————————————————————————
当servlet容器创建完成后,ContextLoaderListener 会监听到该事件的发生,然后就会执行 contextInitialized 方法。
1、contextInitialized 方法中的 initWebApplicationContext(event.getServletContext()) 方法。初始化容器。
	1、 判断当前对象的 context 属性是否为 ConfigurableWebApplicationContext 类型。
		这个 context 是上面创建并注册在servlet容器中的对象,类型是 AnnotationConfigWebApplicationContext 的。
	2、 如果是 ConfigurableWebApplicationContext 类型。
		1、 强转为 ConfigurableWebApplicationContext 类型。
		2、 如果没有激活
			1、 如果父容器为空。会先加载父容器,然后设置到当前容器中。
			2、 执行 configureAndRefreshWebApplicationContext,配置并且刷新容器。
				1、 先对 ConfigurableWebApplicationContext 类型的容器进行 id 有无的校验。
				2、 设置 容器的 ServletContext 。
				3、 获取 容器的环境,满住一定条件执行初始化操作。
				4、 自定义的context操作。
				5、 执行容器刷新。  这里就到了加载IOC容器的过程中,会创建bean。

————————————————————————————————servlet容器创建后,创建 web 容器————————————————————————————————
入口位于: HttpServletBean 的init方法。
1、 获取初始化参数,设置到一些bean中
2、 initServletBean 初始化web容器。
	1、 initWebApplicationContext 先初始化web容器
		1、 如果当前对象(FrameworkServlet)的webApplicationContext 属性为不为空。
			1、 如果是 ConfigurableWebApplicationContext 类型。
				1、 强转为 ConfigurableWebApplicationContext 类型。
				2、 如果没有激活
					1、 如果父容器为空。会先加载父容器,然后设置到当前容器中。
					2、 执行 configureAndRefreshWebApplicationContext,配置并且刷新容器。
						1、 先对 ConfigurableWebApplicationContext 类型的容器进行 id 有无的校验。
						2、 设置 容器的 ServletContext 。
						3、 获取 容器的环境,满住一定条件执行初始化操作。
						4、 自定义的context操作。
						5、 执行容器刷新。  这里就到了加载IOC容器的过程中,会创建bean。
		2、 findWebApplicationContext 查找可用的 ApplicationContext ,赋值给 wac 。
		3、 如果 wac 还为空,就需要调用 createWebApplicationContext 方法创建一个 ApplicationContext 。
		4、 刷新事件接受、发布context(设置到servletContext中),返回wac对象。
	2、 initFrameworkServlet 在初始化Servlet。 这个方法默认什么都不做,可以被子类重写。

最后

在网上看了一些博客,看了一些视频。才写了这两篇对spring源码的一些简单分析的文章,因为对一些东西的理解不是太深,可能会导致表达有误,欢迎大家指出问题所在,我们一起进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值