本篇文章接着上篇: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源码的一些简单分析的文章,因为对一些东西的理解不是太深,可能会导致表达有误,欢迎大家指出问题所在,我们一起进步。