原创

Spring源码分析

一、Spring依赖注入有三种实现方式:

1.构造器注入

2.Setter注入

3.FactoryBean接口注入

二、Spring三种配置方式:

1.XML

2.注解

3.Java的配置

三、Spring初始化过程:

1.初始化beanFactory,加载BeanDefinition的核心类和方法

new ClassPathXmlApplicationContext("aop-xml.xml");

AbstractApplicationContext.refresh();

//初始化内部beanfactory
AbstractApplicationContext.obtainFreshBeanFactory();

AbstractRefreshableApplicationContext.refreshBeanFactory();

AbstractXmlApplicationContext.loadBeanDefinitions();

AbstractBeanDefinitionReader.loadBeanDefinitions();

XmlBeanDefinitionReader.loadBeanDefinitions();

XmlBeanDefinitionReader.doLoadBeanDefinitions();

XmlBeanDefinitionReader.registerBeanDefinitions();

DefaultBeanDefinitionDocumentReader.registerBeanDefinitions();

DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions();

DefaultBeanDefinitionDocumentReader.parseBeanDefinitions();

//默认命名空间解析
DefaultBeanDefinitionDocumentReader.parseDefaultElement();

//除了默认的,剩下的bean解析都是走下面方法
BeanDefinitionParserDelegate.parseCustomElement();

(接口)NamespaceHandler.parse();
//这里的命名空间是spring的一个拓展点,aop,webmvc==其他所有非beans包的spring功能都是通过这个接口拓展的,具体想看某个包的解析过程,找到对应的jar包,查看META-INF目录下的spring.handlers,他定义的xml格式文件在spring.schemas文件里面

Aop的命名空间为org.springframework.aop.config.AopNamespaceHandler

Webmvc的命名空间为org.springframework.web.servlet.config.MvcNamespaceHandler

Springjdbc的命名空间为org.springframework.jdbc.config.JdbcNamespaceHandler


2.初始化bean一个普通分支

AbstractBeanFactory.getBean();

AbstractBeanFactory.doGetBean();

AbstractAutowireCapableBeanFactory.createBean();

AbstractAutowireCapableBeanFactory.doCreateBean();

//这里初始化bean的BeanWrapper(wrapper结尾的表示都是包装过的类,dubbo里面wrapper结尾的都是aop之后的类)
AbstractAutowireCapableBeanFactory.createBeanInstance();

//填充属性
AbstractAutowireCapableBeanFactory.populateBean();

AbstractAutowireCapableBeanFactory.autowireByName();

AbstractAutowireCapableBeanFactory.autowireByType();

AbstractAutowireCapableBeanFactory.applyPropertyValues();

AbstractPropertyAccessor.setPropertyValues();

AbstractPropertyAccessor.setPropertyValue();

AbstractNestablePropertyAccessor.setPropertyValue();

AbstractNestablePropertyAccessor.processKeyedProperty();

AbstractNestablePropertyAccessor.processLocalProperty();

//初始化
AbstractAutowireCapableBeanFactory.initializeBean();

AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization();

AbstractAutowireCapableBeanFactory.invokeInitMethods();

//大名鼎鼎的spring-aop就是这里实现bean增强的
AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization();


3.Aop的实现原理

AopNamespaceHandler.init();

AspectJAutoProxyBeanDefinitionParser.parse();

AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary();

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary();

AopConfigUtils.registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class);

//这里将他注册到beanfactory
AopConfigUtils.registerOrEscalateApcAsRequired();

注意这里的AnnotationAwareAspectJAutoProxyCreator,他有个接口为BeanPostProcessor

这个在getBean里面的AbstractAutowireCapableBeanFactory.initializeBean();里面发挥用处

AbstractAutoProxyCreator.postProcessAfterInitialization();

AbstractAutoProxyCreator.wrapIfNecessary();

AbstractAutoProxyCreator.createProxy();

ProxyFactory.getProxy();

//这里的proxyfactory有两种,JdkProxyFactory,CglibProxyFactory
ProxyFactory.createAopProxy().getProxy(classLoader);

4.两种字节码技术区别

JDK动态代理是需要被代理的类实现InvocationHandler接口,JDK动态代理只能对实现了接口的类生成代理,而不能针对类。

CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final,对于final类或方法,是无法继承的。

四、SpringMvc源码解析

1.web容器启动的时候初始化web.xml里面的servlet,并且会调用servlet里面的init方法,当请求过来会匹配路径,如果路径匹配会调用servlet的service方法,这是javaee的规定

2.一般在web.xml里面配置DispatcherServlet,具体初始化流程:

HttpServletBean.init();

HttpServletBean.initServletBean();

FrameworkServlet.initServletBean();

FrameworkServlet.initWebApplicationContext();

FrameworkServlet.createWebApplicationContext();

FrameworkServlet.configureAndRefreshWebApplicationContext();

AbstractApplicationContext.refresh();//又跑到这里面来了

FrameworkServlet.onRefresh();

DispatcherServlet.onRefresh();

DispatcherServlet.initStrategies();

DispatcherServlet.initHandlerMappings();

//请求响应流程
GenericServlet.service();

HttpServlet.service();

FrameworkServlet.service();

FrameworkServlet.processRequest();

DispatcherServlet.doService();

DispatcherServlet.doDispatch();

//这里是处理逻辑
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

AnnotationMethodHandlerAdapter.handle();

//这里通过req获得mathod,执行之后返回Object,将他转换成ModelAndView进入下一环节
AnnotationMethodHandlerAdapter.invokeHandlerMethod();

//这里是绘制view
DispatcherServlet.processDispatchResult();

DispatcherServlet.render();

DispatcherServlet.resolveViewName();//解析成view通过名字

AbstractCachingViewResolver.createView();

UrlBasedViewResolver.loadView();

InternalResourceViewResolver.buildView();

//UrlBasedViewResolver可以自己定义

UrlBasedViewResolver.buildView();

AbstractView.renderMergedOutputModel();

InternalResourceView.renderMergedOutputModel();//渲染

RequestDispatcher.forward();//跳转到jsp或者html


3.JSP运行过程

Tomcat源码下载地址 https://github.com/apache/tomcat

① 将JSP文件翻译成servlet源代码;

② 将servlet源代码编译成字节码文件;

③ 载入字节码并实例化和初始化;

① Tomat将http请求通过servlet转给JspServlet

② JspServlet在JspRuntimeContext的上下文中查找JspServletWrapper,如果没有找到就新建实例,找到了话就取出来用

③ JspServletWrapper初始化时也会初始化一个JspCompilationContext

④ JspServlet将请求转给JspServletWrapper的service方法进行处理

⑤ JspServletWrapper将判断系统是否允许重加载this.options.getDevelopment,如果允许将调用JspCompilationContext的编译方法compile

⑥ JspCompilationContext的compile方法通过判断jsp文件的时间戳来决定是否将类加载器JsperLoader的引用置null

⑦ JspServletWrapper通过getServlet方法从JspCompilationContext加载(load方法)jsp编译后的class类,并实例化

⑧ JspCompilationContext类在load时,首先要获得JsperLoader,如果它为null将新建一个实例,然后让JsperLoader这个类加载器加载jsp的class

⑨ JspServletWrapper获得实例化的servlet后,将把JspServlet转过来的请求交由这个servlet处理源码简要分析如下:

源码简要分析如下:

3.1、源码中涉及到的几个重要文件

JspServlet.java、JspServletWrap.java、JspRuntimeContext.java、Compiler.java、JDTCompiler.java(AntCompiler.java)

3.2、代码详细分析

JspServlet中涉及两重要方法:service方法和serviceJspFile,service方法主要用于获取请求JSP资源路径,serviceJspFile主要用于构建JspServletWrap。

JspRuntimeContext主要提供JspServletWrap的容器(用的是ConcurrentHashMap集合)。

Compiler主要用来翻译JSP文件和将其编译成字节码,具体的字节码产生实现由其子类实现(用到模版方法设计模式)。

JDTCompiler(AntCompiler)主要用来产生字节码文件。

JspServletWrap主要用来实例化Servlet并调用init进行初始化处理,并且调用servlet的service方法进行处理请求。

五、bean的生命周期

  1. Bean的建立, 由BeanFactory读取Bean定义文件,并生成各个实例
  2. Setter注入,执行Bean的属性依赖注入
  3. BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法
  4. BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法
  5. BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization()方法
  6. InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行其afterPropertiesSet()方法
  7. Bean定义文件中定义init-method
  8. BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法
  9. DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法
  10. Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法

正文到此结束
本文目录