diff --git a/note/Spring.md b/note/Spring.md index 6424696..0bc359e 100644 --- a/note/Spring.md +++ b/note/Spring.md @@ -1,3 +1,105 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [基本](#%E5%9F%BA%E6%9C%AC) + - [ClassPathXmlApplicationContext](#classpathxmlapplicationcontext) + - [构造器](#%E6%9E%84%E9%80%A0%E5%99%A8) + - [设置配置文件路径](#%E8%AE%BE%E7%BD%AE%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%B7%AF%E5%BE%84) + - [Environment接口](#environment%E6%8E%A5%E5%8F%A3) + - [Profile](#profile) + - [Property](#property) + - [Environment构造器](#environment%E6%9E%84%E9%80%A0%E5%99%A8) + - [PropertySources接口](#propertysources%E6%8E%A5%E5%8F%A3) + - [PropertySource接口](#propertysource%E6%8E%A5%E5%8F%A3) + - [路径Placeholder处理](#%E8%B7%AF%E5%BE%84placeholder%E5%A4%84%E7%90%86) + - [PropertyResolver接口](#propertyresolver%E6%8E%A5%E5%8F%A3) + - [解析](#%E8%A7%A3%E6%9E%90) + - [refresh](#refresh) + - [prepareRefresh](#preparerefresh) + - [属性校验](#%E5%B1%9E%E6%80%A7%E6%A0%A1%E9%AA%8C) + - [BeanFactory创建](#beanfactory%E5%88%9B%E5%BB%BA) + - [BeanFactory接口](#beanfactory%E6%8E%A5%E5%8F%A3) + - [BeanFactory定制](#beanfactory%E5%AE%9A%E5%88%B6) + - [Bean加载](#bean%E5%8A%A0%E8%BD%BD) + - [EntityResolver](#entityresolver) + - [BeanDefinitionReader](#beandefinitionreader) + - [路径解析(Ant)](#%E8%B7%AF%E5%BE%84%E8%A7%A3%E6%9E%90ant) + - [配置文件加载](#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%8A%A0%E8%BD%BD) + - [Bean解析](#bean%E8%A7%A3%E6%9E%90) + - [默认命名空间解析](#%E9%BB%98%E8%AE%A4%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E8%A7%A3%E6%9E%90) + - [import](#import) + - [alias](#alias) + - [bean](#bean) + - [id & name处理](#id--name%E5%A4%84%E7%90%86) + - [beanName生成](#beanname%E7%94%9F%E6%88%90) + - [bean解析](#bean%E8%A7%A3%E6%9E%90) + - [Bean装饰](#bean%E8%A3%85%E9%A5%B0) + - [Bean注册](#bean%E6%B3%A8%E5%86%8C) + - [BeanDefiniton数据结构](#beandefiniton%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84) + - [beans](#beans) + - [其它命名空间解析](#%E5%85%B6%E5%AE%83%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E8%A7%A3%E6%9E%90) + - [NamespaceHandler继承体系](#namespacehandler%E7%BB%A7%E6%89%BF%E4%BD%93%E7%B3%BB) + - [init](#init) + - [BeanFactory数据结构](#beanfactory%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84) + - [prepareBeanFactory](#preparebeanfactory) + - [BeanExpressionResolver](#beanexpressionresolver) + - [PropertyEditorRegistrar](#propertyeditorregistrar) + - [环境注入](#%E7%8E%AF%E5%A2%83%E6%B3%A8%E5%85%A5) + - [依赖解析忽略](#%E4%BE%9D%E8%B5%96%E8%A7%A3%E6%9E%90%E5%BF%BD%E7%95%A5) + - [bean伪装](#bean%E4%BC%AA%E8%A3%85) + - [LoadTimeWeaver](#loadtimeweaver) + - [注册环境](#%E6%B3%A8%E5%86%8C%E7%8E%AF%E5%A2%83) + - [postProcessBeanFactory](#postprocessbeanfactory) + - [invokeBeanFactoryPostProcessors](#invokebeanfactorypostprocessors) + - [BeanPostProcessor注册](#beanpostprocessor%E6%B3%A8%E5%86%8C) + - [MessageSource](#messagesource) + - [事件驱动](#%E4%BA%8B%E4%BB%B6%E9%A9%B1%E5%8A%A8) + - [事件](#%E4%BA%8B%E4%BB%B6) + - [发布者](#%E5%8F%91%E5%B8%83%E8%80%85) + - [ApplicationEventPublisher](#applicationeventpublisher) + - [ApplicationEventMulticaster](#applicationeventmulticaster) + - [监听器](#%E7%9B%91%E5%90%AC%E5%99%A8) + - [初始化](#%E5%88%9D%E5%A7%8B%E5%8C%96) + - [事件发布](#%E4%BA%8B%E4%BB%B6%E5%8F%91%E5%B8%83) + - [监听器获取](#%E7%9B%91%E5%90%AC%E5%99%A8%E8%8E%B7%E5%8F%96) + - [同步/异步](#%E5%90%8C%E6%AD%A5%E5%BC%82%E6%AD%A5) + - [全局](#%E5%85%A8%E5%B1%80) + - [注解](#%E6%B3%A8%E8%A7%A3) + - [onRefresh](#onrefresh) + - [ApplicationListener注册](#applicationlistener%E6%B3%A8%E5%86%8C) + - [singleton初始化](#singleton%E5%88%9D%E5%A7%8B%E5%8C%96) + - [ConversionService](#conversionservice) + - [StringValueResolver](#stringvalueresolver) + - [LoadTimeWeaverAware](#loadtimeweaveraware) + - [初始化](#%E5%88%9D%E5%A7%8B%E5%8C%96-1) +- [getBean](#getbean) + - [beanName转化](#beanname%E8%BD%AC%E5%8C%96) + - [手动注册bean检测](#%E6%89%8B%E5%8A%A8%E6%B3%A8%E5%86%8Cbean%E6%A3%80%E6%B5%8B) + - [检查父容器](#%E6%A3%80%E6%9F%A5%E7%88%B6%E5%AE%B9%E5%99%A8) + - [依赖初始化](#%E4%BE%9D%E8%B5%96%E5%88%9D%E5%A7%8B%E5%8C%96) + - [Singleton初始化](#singleton%E5%88%9D%E5%A7%8B%E5%8C%96) + - [getSingleton方法](#getsingleton%E6%96%B9%E6%B3%95) + - [是否存在](#%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8) + - [bean创建](#bean%E5%88%9B%E5%BB%BA) + - [lookup-method检测](#lookup-method%E6%A3%80%E6%B5%8B) + - [InstantiationAwareBeanPostProcessor触发](#instantiationawarebeanpostprocessor%E8%A7%A6%E5%8F%91) + - [doCreateBean](#docreatebean) + - [创建(createBeanInstance)](#%E5%88%9B%E5%BB%BAcreatebeaninstance) + - [MergedBeanDefinitionPostProcessor](#mergedbeandefinitionpostprocessor) + - [属性解析](#%E5%B1%9E%E6%80%A7%E8%A7%A3%E6%9E%90) + - [属性设置](#%E5%B1%9E%E6%80%A7%E8%AE%BE%E7%BD%AE) + - [初始化](#%E5%88%9D%E5%A7%8B%E5%8C%96-2) + - [getObjectForBeanInstance](#getobjectforbeaninstance) + - [Prototype初始化](#prototype%E5%88%9D%E5%A7%8B%E5%8C%96) + - [beforePrototypeCreation](#beforeprototypecreation) + - [createBean](#createbean) + - [afterPrototypeCreation](#afterprototypecreation) + - [总结](#%E6%80%BB%E7%BB%93) + - [其它Scope初始化](#%E5%85%B6%E5%AE%83scope%E5%88%9D%E5%A7%8B%E5%8C%96) + + + # 基本 本部分从最基本的Spring开始。配置文件: @@ -118,11 +220,11 @@ protected ConfigurableEnvironment createEnvironment() { ![Environment继承体系](images/Environment.jpg) -Environmen接口**代表了当前应用所处的环境。**从此接口的方法可以看出,其主要和profile、Property相关。 +Environmen接口**代表了当前应用所处的环境。** 从此接口的方法可以看出,其主要和profile、Property相关。 ##### Profile -Spring Profile特性是从3.1开始的,其主要是为了解决这样一种问题: 线上环境和测试环境使用不同的配置或是数据库或是其它。有了Profile便可以在 不同环境之间无缝切换。**Spring容器管理的所有bean都是和一个profile绑定在一起的。**使用了Profile的配置文件示例: +Spring Profile特性是从3.1开始的,其主要是为了解决这样一种问题: 线上环境和测试环境使用不同的配置或是数据库或是其它。有了Profile便可以在 不同环境之间无缝切换。**Spring容器管理的所有bean都是和一个profile绑定在一起的。** 使用了Profile的配置文件示例: ```xml diff --git a/note/flows/spring_application_run.gliffy b/note/flows/spring_application_run.gliffy new file mode 100644 index 0000000..7b7d4de --- /dev/null +++ b/note/flows/spring_application_run.gliffy @@ -0,0 +1 @@ +{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":541,"y":993,"rotation":0,"id":61,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":61,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-1,-3],[-1,32],[306,32],[306,67]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":55,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":58,"px":0.5,"py":0}}},"linkMap":[]},{"x":797,"y":1060,"rotation":0,"id":58,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.start_end","width":100,"height":40,"lockAspectRatio":false,"lockShape":false,"order":58,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.start_end.flowchart_v1","strokeWidth":2,"strokeColor":"#990000","fillColor":"#990000","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":60,"uid":null,"width":96,"height":20,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

finished

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":544,"y":900,"rotation":0,"id":57,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":57,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-4,0],[-4,50]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":55,"px":0.5,"py":0}}},"linkMap":[]},{"x":853,"y":820,"rotation":0,"id":54,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":33,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-6,0],[-6,20],[-313,20],[-313,40]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":49,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":52,"px":0.5,"py":0}}},"linkMap":[]},{"x":849,"y":739,"rotation":0,"id":51,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":30,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-2,1],[-2,41]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":45,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":49,"px":0.5,"py":0}}},"linkMap":[]},{"x":539,"y":661,"rotation":0,"id":47,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":27,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[1,-1],[1,19],[308,19],[308,39]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":35,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":45,"px":0.5,"py":0}}},"linkMap":[]},{"x":848,"y":414,"rotation":0,"id":43,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":24,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-1,-4],[-1,16],[-308,16],[-308,36]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":38,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":26,"px":0.5,"py":0}}},"linkMap":[]},{"x":542,"y":325,"rotation":0,"id":41,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":23,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-2,-5],[-2,20],[305,20],[305,45]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":21,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":38,"px":0.5,"py":0}}},"linkMap":[]},{"x":847,"y":236,"rotation":0,"id":24,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":12,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[0,-6],[0,19],[-307,19],[-307,44]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":12,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":21,"px":0.5,"py":0}}},"linkMap":[]},{"x":490,"y":280,"rotation":0,"id":21,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":40,"lockAspectRatio":false,"lockShape":false,"order":10,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#1c4587","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":23,"uid":null,"width":96,"height":20,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

环境准备

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":851,"y":191,"rotation":0,"id":19,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":9,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":2,"endArrow":0,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-4,-1],[-4,-21],[-311,-21],[-311,-41]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":12,"px":0.5,"py":0}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":9,"px":0.5,"py":1}}},"linkMap":[]},{"x":797,"y":190,"rotation":0,"id":12,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":40,"lockAspectRatio":false,"lockShape":false,"order":7,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#ffffff","fillColor":"#990000","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":14,"uid":null,"width":96,"height":27,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

starting

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":490,"y":120,"rotation":0,"id":9,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.start_end","width":100,"height":30,"lockAspectRatio":false,"lockShape":false,"order":5,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.start_end.flowchart_v1","strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#0B599F","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":11,"uid":null,"width":96,"height":20,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

进入

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":436,"y":80,"rotation":0,"id":5,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":231,"height":20,"lockAspectRatio":false,"lockShape":false,"order":2,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

SpringApplication

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":390,"y":82,"rotation":0,"id":1,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":0,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":"4.0,4.0","startArrow":0,"endArrow":0,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":0,"controlPath":[[0,0],[2.8421709430404007e-13,1062.0169490172932]],"lockSegments":{}}},"children":null,"linkMap":[]},{"x":690,"y":82,"rotation":0,"id":4,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":1,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":"4.0,4.0","startArrow":0,"endArrow":0,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":0,"controlPath":[[0,0],[0,1067.0074976306398]],"lockSegments":{}}},"children":null,"linkMap":[]},{"x":987,"y":87,"rotation":0,"id":7,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":3,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":"4.0,4.0","startArrow":0,"endArrow":0,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":0,"controlPath":[[0,0],[-1.1368683772161603e-13,1051.0171264066062]],"lockSegments":{}}},"children":null,"linkMap":[]},{"x":720,"y":70,"rotation":0,"id":8,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":250.00000000000003,"height":40,"lockAspectRatio":false,"lockShape":false,"order":4,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

SpringApplicationRunListener

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":722,"y":370,"rotation":0,"id":38,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":250,"height":40,"lockAspectRatio":false,"lockShape":false,"order":21,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#ffffff","fillColor":"#990000","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":4.999999999999998,"y":0,"rotation":0,"id":39,"uid":null,"width":239.99999999999997,"height":27,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

environmentPrepared

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":541,"y":583,"rotation":0,"id":37,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":20,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-1,-3],[-1,37]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":31,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":35,"px":0.5,"py":0}}},"linkMap":[]},{"x":480,"y":620,"rotation":0,"id":35,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":120,"height":40,"lockAspectRatio":false,"lockShape":false,"order":18,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#1c4587","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.4,"y":0,"rotation":0,"id":36,"uid":null,"width":115.19999999999999,"height":20,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

context准备

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":542,"y":494,"rotation":0,"id":33,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":17,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-2,-4],[-2,46]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":26,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":31,"px":0.5,"py":0}}},"linkMap":[]},{"x":480,"y":540,"rotation":0,"id":31,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":120,"height":40,"lockAspectRatio":false,"lockShape":false,"order":15,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#1c4587","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.4,"y":0,"rotation":0,"id":32,"uid":null,"width":115.19999999999999,"height":20,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

context创建

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":480,"y":450,"rotation":0,"id":26,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":120,"height":40,"lockAspectRatio":false,"lockShape":false,"order":13,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#1c4587","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.4,"y":0,"rotation":0,"id":27,"uid":null,"width":115.19999999999999,"height":20,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

Banner打印

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":737,"y":700,"rotation":0,"id":45,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":220,"height":40,"lockAspectRatio":false,"lockShape":false,"order":25,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#ffffff","fillColor":"#990000","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":4.399999999999999,"y":0,"rotation":0,"id":46,"uid":null,"width":211.2,"height":27,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

contextPrepared

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":737,"y":780,"rotation":0,"id":49,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":220,"height":40,"lockAspectRatio":false,"lockShape":false,"order":28,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#ffffff","fillColor":"#990000","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":4.399999999999999,"y":0,"rotation":0,"id":50,"uid":null,"width":211.2,"height":27,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

contextLoaded

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":470,"y":860,"rotation":0,"id":52,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":140,"height":40,"lockAspectRatio":false,"lockShape":false,"order":31,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#1c4587","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.8000000000000003,"y":0,"rotation":0,"id":53,"uid":null,"width":134.4,"height":20,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

refreshContext

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":470,"y":950,"rotation":0,"id":55,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":140,"height":40,"lockAspectRatio":false,"lockShape":false,"order":35,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#1c4587","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.8000000000000003,"y":0,"rotation":0,"id":56,"uid":null,"width":134.4,"height":20,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

runner调用

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]}],"background":"#FFFFFF","width":992,"height":1154,"maxWidth":5000,"maxHeight":5000,"nodeIndex":62,"autoFit":true,"exportBorder":false,"gridOn":true,"snapToGrid":true,"drawingGuidesOn":true,"pageBreaksOn":false,"printGridOn":false,"printPaper":"LETTER","printShrinkToFit":false,"printPortrait":true,"shapeStyles":{"com.gliffy.shape.flowchart.flowchart_v1.default":{"fill":"#990000","stroke":"#990000","strokeWidth":2}},"lineStyles":{"global":{"stroke":"#0B599F","strokeWidth":2,"dashStyle":null,"orthoMode":0,"fill":"none","startArrow":0,"endArrow":2}},"textStyles":{},"themeData":{"uid":"com.gliffy.theme.blueprint","name":"Blueprint","shape":{"primary":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#DDE6F1","gradient":false,"dropShadow":false,"opacity":1,"text":{"color":"#08233F","bold":null,"italic":null,"underline":null}},"secondary":{"strokeWidth":2,"strokeColor":"#08233F","fillColor":"#424D76","gradient":false,"dropShadow":false,"opacity":1,"text":{"color":"#FFFFFF","bold":null,"italic":null,"underline":null}},"tertiary":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"opacity":1,"text":{"color":"#08233F","bold":null,"italic":null,"underline":null}},"highlight":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"#0B599F","gradient":false,"dropShadow":false,"opacity":1,"text":{"color":"#ffffff","bold":null,"italic":null,"underline":null}}},"line":{"strokeWidth":2,"strokeColor":"#0B599F","fillColor":"none","arrowType":2,"interpolationType":"linear","cornerRadius":0,"text":{"color":"#08233F","bold":null,"italic":null,"underline":null}},"text":{"color":"#08233F","bold":null,"italic":null,"underline":null},"stage":{"color":"#FFFFFF"}}}} \ No newline at end of file diff --git a/note/guava-cache.md b/note/guava-cache.md index e9ed021..f729c2f 100644 --- a/note/guava-cache.md +++ b/note/guava-cache.md @@ -1,3 +1,37 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [创建](#%E5%88%9B%E5%BB%BA) + - [数据结构](#%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84) + - [segments](#segments) + - [ReferenceEntry](#referenceentry) + - [初始化](#%E5%88%9D%E5%A7%8B%E5%8C%96) + - [ReferenceEntry数组](#referenceentry%E6%95%B0%E7%BB%84) + - [引用队列](#%E5%BC%95%E7%94%A8%E9%98%9F%E5%88%97) +- [put](#put) + - [Hash算法](#hash%E7%AE%97%E6%B3%95) + - [ReHash](#rehash) + - [Segment选取](#segment%E9%80%89%E5%8F%96) + - [Segment.put](#segmentput) + - [线程安全性](#%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E6%80%A7) + - [过期/垃圾缓存清理](#%E8%BF%87%E6%9C%9F%E5%9E%83%E5%9C%BE%E7%BC%93%E5%AD%98%E6%B8%85%E7%90%86) + - [垃圾缓存](#%E5%9E%83%E5%9C%BE%E7%BC%93%E5%AD%98) + - [善后](#%E5%96%84%E5%90%8E) + - [writeQueue移除](#writequeue%E7%A7%BB%E9%99%A4) + - [accessQueue移除](#accessqueue%E7%A7%BB%E9%99%A4) + - [加载终止](#%E5%8A%A0%E8%BD%BD%E7%BB%88%E6%AD%A2) + - [移除算法](#%E7%A7%BB%E9%99%A4%E7%AE%97%E6%B3%95) + - [过期缓存](#%E8%BF%87%E6%9C%9F%E7%BC%93%E5%AD%98) + - [扩容](#%E6%89%A9%E5%AE%B9) + - [设值](#%E8%AE%BE%E5%80%BC) +- [get(key)](#getkey) + - [get(key,hash,loader)](#getkeyhashloader) +- [参考](#%E5%8F%82%E8%80%83) +- [总结](#%E6%80%BB%E7%BB%93) + + + # 创建 以CacheLoader的方式为例: diff --git a/note/images/ApplicationContextInitializer.png b/note/images/ApplicationContextInitializer.png new file mode 100644 index 0000000..74ce928 Binary files /dev/null and b/note/images/ApplicationContextInitializer.png differ diff --git a/note/images/ApplicationListener.png b/note/images/ApplicationListener.png new file mode 100644 index 0000000..51929f6 Binary files /dev/null and b/note/images/ApplicationListener.png differ diff --git a/note/images/ApplicationListener_used.png b/note/images/ApplicationListener_used.png new file mode 100644 index 0000000..e765e52 Binary files /dev/null and b/note/images/ApplicationListener_used.png differ diff --git a/note/images/DataBinder.jpg b/note/images/DataBinder.jpg new file mode 100644 index 0000000..af2236c Binary files /dev/null and b/note/images/DataBinder.jpg differ diff --git a/note/images/EnvironmentPostProcessor.png b/note/images/EnvironmentPostProcessor.png new file mode 100644 index 0000000..61af994 Binary files /dev/null and b/note/images/EnvironmentPostProcessor.png differ diff --git a/note/images/ServletModelAttributeMethodProcessor.jpg b/note/images/ServletModelAttributeMethodProcessor.jpg new file mode 100644 index 0000000..4b5f83e Binary files /dev/null and b/note/images/ServletModelAttributeMethodProcessor.jpg differ diff --git a/note/images/SpringApplicationRunListener.png b/note/images/SpringApplicationRunListener.png new file mode 100644 index 0000000..84333c4 Binary files /dev/null and b/note/images/SpringApplicationRunListener.png differ diff --git a/note/images/Validator.png b/note/images/Validator.png new file mode 100644 index 0000000..85aa28f Binary files /dev/null and b/note/images/Validator.png differ diff --git a/note/images/WebDataBinderFactory.jpg b/note/images/WebDataBinderFactory.jpg new file mode 100644 index 0000000..0e70dd0 Binary files /dev/null and b/note/images/WebDataBinderFactory.jpg differ diff --git a/note/images/cglib_invocation.png b/note/images/cglib_invocation.png new file mode 100644 index 0000000..6091a98 Binary files /dev/null and b/note/images/cglib_invocation.png differ diff --git a/note/images/spring_application_run.png b/note/images/spring_application_run.png new file mode 100644 index 0000000..b12727d Binary files /dev/null and b/note/images/spring_application_run.png differ diff --git a/note/images/start_event_listener.png b/note/images/start_event_listener.png new file mode 100644 index 0000000..dfbe55f Binary files /dev/null and b/note/images/start_event_listener.png differ diff --git a/note/spring-aop.md b/note/spring-aop.md index 341be7b..4a6d4da 100644 --- a/note/spring-aop.md +++ b/note/spring-aop.md @@ -1,3 +1,80 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [开头](#%E5%BC%80%E5%A4%B4) +- [aop:config](#aopconfig) + - [解析](#%E8%A7%A3%E6%9E%90) + - [proxy-target-class & expose-proxy](#proxy-target-class--expose-proxy) + - [aop:pointcut](#aoppointcut) + - [aop:advisor](#aopadvisor) + - [aop:aspect](#aopaspect) + - [aop:declare-parents](#aopdeclare-parents) + - [其它](#%E5%85%B6%E5%AE%83) + - [MethodLocatingFactoryBean](#methodlocatingfactorybean) + - [SimpleBeanFactoryAwareAspectInstanceFactory](#simplebeanfactoryawareaspectinstancefactory) + - [总结](#%E6%80%BB%E7%BB%93) + - [代理子类生成](#%E4%BB%A3%E7%90%86%E5%AD%90%E7%B1%BB%E7%94%9F%E6%88%90) + - [入口](#%E5%85%A5%E5%8F%A3) + - [postProcessBeforeInstantiation](#postprocessbeforeinstantiation) + - [调用时机](#%E8%B0%83%E7%94%A8%E6%97%B6%E6%9C%BA) + - [源码](#%E6%BA%90%E7%A0%81) + - [应该代理 ?](#%E5%BA%94%E8%AF%A5%E4%BB%A3%E7%90%86-) + - [基础类检测](#%E5%9F%BA%E7%A1%80%E7%B1%BB%E6%A3%80%E6%B5%8B) + - [跳过类检测](#%E8%B7%B3%E8%BF%87%E7%B1%BB%E6%A3%80%E6%B5%8B) + - [AOP逻辑](#aop%E9%80%BB%E8%BE%91) + - [Advisor寻找](#advisor%E5%AF%BB%E6%89%BE) + - [适用性检测](#%E9%80%82%E7%94%A8%E6%80%A7%E6%A3%80%E6%B5%8B) + - [检测结果缓存](#%E6%A3%80%E6%B5%8B%E7%BB%93%E6%9E%9C%E7%BC%93%E5%AD%98) + - [TargetSource](#targetsource) + - [postProcessAfterInitialization](#postprocessafterinitialization) + - [Advisor寻找](#advisor%E5%AF%BB%E6%89%BE-1) + - [适用性判断](#%E9%80%82%E7%94%A8%E6%80%A7%E5%88%A4%E6%96%AD) + - [引入](#%E5%BC%95%E5%85%A5) + - [其它](#%E5%85%B6%E5%AE%83-1) + - [Advisor扩展](#advisor%E6%89%A9%E5%B1%95) + - [排序](#%E6%8E%92%E5%BA%8F) + - [创建](#%E5%88%9B%E5%BB%BA) + - [JDK动态代理 or Cglib](#jdk%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86-or-cglib) + - [JDK动态代理](#jdk%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86) + - [equals & hashCode](#equals--hashcode) + - [链式调用](#%E9%93%BE%E5%BC%8F%E8%B0%83%E7%94%A8) + - [Cglib](#cglib) +- [aop:scoped-proxy](#aopscoped-proxy) + - [解析](#%E8%A7%A3%E6%9E%90-1) + - [入口](#%E5%85%A5%E5%8F%A3-1) + - [装饰](#%E8%A3%85%E9%A5%B0) + - [代理生成](#%E4%BB%A3%E7%90%86%E7%94%9F%E6%88%90) + - [Advisor](#advisor) + - [引入](#%E5%BC%95%E5%85%A5-1) + - [例子](#%E4%BE%8B%E5%AD%90) + - [自定义Scope](#%E8%87%AA%E5%AE%9A%E4%B9%89scope) + - [配置](#%E9%85%8D%E7%BD%AE) + - [测试](#%E6%B5%8B%E8%AF%95) + - [原理](#%E5%8E%9F%E7%90%86) + - [doGetBean](#dogetbean) + - [代理子类](#%E4%BB%A3%E7%90%86%E5%AD%90%E7%B1%BB) + - [CallbackFilter & Callback](#callbackfilter--callback) + - [Callback](#callback) + - [CallbackFilter](#callbackfilter) + - [回调](#%E5%9B%9E%E8%B0%83) +- [aop:aspectj-autoproxy](#aopaspectj-autoproxy) + - [属性](#%E5%B1%9E%E6%80%A7) + - [proxy-target-class](#proxy-target-class) + - [expose-proxy](#expose-proxy) + - [栗子](#%E6%A0%97%E5%AD%90) + - [切面](#%E5%88%87%E9%9D%A2) + - [被代理类](#%E8%A2%AB%E4%BB%A3%E7%90%86%E7%B1%BB) + - [配置](#%E9%85%8D%E7%BD%AE-1) + - [解析](#%E8%A7%A3%E6%9E%90-2) + - [原理](#%E5%8E%9F%E7%90%86-1) + - [总结](#%E6%80%BB%E7%BB%93-1) +- [拾遗](#%E6%8B%BE%E9%81%97) + - [AOP切面的坑](#aop%E5%88%87%E9%9D%A2%E7%9A%84%E5%9D%91) + - [总结](#%E6%80%BB%E7%BB%93-2) + + + # 开头 aop部分的解析器由AopNamespaceHandler注册,其init方法: @@ -1145,4 +1222,60 @@ public boolean isAspect(Class clazz) { ## 总结 -Spring对于AspectJ风格AOP的支持停留在外表(注解)上面,内部的实现仍然是自己的东西。 \ No newline at end of file +Spring对于AspectJ风格AOP的支持停留在外表(注解)上面,内部的实现仍然是自己的东西。 + +# 拾遗 + +## AOP切面的坑 + +1. 定义在private方法上的切面不会被执行,这个很容易理解,毕竟子类不能覆盖父类的私有方法。 +2. 同一个代理子类内部的方法相互调用不会再次执行切面。 + +这里以Cglib为例对第二点进行说明,cglib的相关核心组件可以参考前面CallbackFilter & Callback部分。对于配置了一个切面的典型场景,Spring内部的执行流程可总结如下图: + +![Cglib调用流程](images/cglib_invocation.png) + +核心便是对目标方法的调用上,这里由CglibMethodInvocation的invokeJoinpoint实现: + +```java +@Override +protected Object invokeJoinpoint() throws Throwable { + if (this.publicMethod) { + return this.methodProxy.invoke(this.target, this.arguments); + } else { + return super.invokeJoinpoint(); + } +} +``` + +如果是非public方法,那么Spring将使用反射的方法对其进行调用,因为反射将其可访问性设为true。MethodProxy是Cglib对方法代理的抽象,这里的关键是**方法调用的对象(目标)是我们的原生类对象,而不是Cglib代理子类的对象,这就从根本上决定了对同类方法的调用不会再次经过切面**。 + +### 总结 + +前面aop:aspectj-autoproxy-属性-expose-proxy一节提到了,Spring允许我们将代理子类暴露出来,可以进行如下配置: + +```xml + + + +``` + +当我们需要在一个被代理方法中调用同类的方法时(此方法也需要经过切面),可以这样调用: + +```java +public void testB() { + System.out.println("testB执行"); + ((SimpleAopBean) AopContext.currentProxy()).testC(); +} +``` + +这里其实是一个ThreadLocal,当Cglib代理子类创建调用链之间便会将代理类设置到其中,DynamicAdvisedInterceptor.intercept相关源码: + +```java +if (this.advised.exposeProxy) { + // Make invocation available if necessary. + oldProxy = AopContext.setCurrentProxy(proxy); + setProxyContext = true; +} +``` + diff --git a/note/spring-boot.md b/note/spring-boot.md new file mode 100644 index 0000000..a05c5ba --- /dev/null +++ b/note/spring-boot.md @@ -0,0 +1,199 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [SpringApplication](#springapplication) + - [web环境检测](#web%E7%8E%AF%E5%A2%83%E6%A3%80%E6%B5%8B) + - [ApplicationContextInitializer](#applicationcontextinitializer) + - [ApplicationListener](#applicationlistener) + - [SpringApplicationRunListener](#springapplicationrunlistener) +- [run](#run) + - [starting](#starting) + - [环境准备](#%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87) + - [属性来源](#%E5%B1%9E%E6%80%A7%E6%9D%A5%E6%BA%90) + - [profile配置](#profile%E9%85%8D%E7%BD%AE) + - [environmentPrepared](#environmentprepared) + - [配置文件加载](#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%8A%A0%E8%BD%BD) + - [SpringApplicationJsonEnvironmentPostProcessor](#springapplicationjsonenvironmentpostprocessor) + - [CloudFoundryVcapEnvironmentPostProcessor](#cloudfoundryvcapenvironmentpostprocessor) + - [ConfigFileApplicationListener](#configfileapplicationlistener) + + + +# SpringApplication + +启动程序首先初始化了一个SpringApplication对象。来看一看在它的构造器了发生了什么。 + +```java +public SpringApplication(ResourceLoader resourceLoader, Object... sources) { + this.resourceLoader = resourceLoader; + initialize(sources); +} +``` + +initialize方法: + +```java +private void initialize(Object[] sources) { + if (sources != null && sources.length > 0) { + this.sources.addAll(Arrays.asList(sources)); + } + this.webEnvironment = deduceWebEnvironment(); + setInitializers((Collection) getSpringFactoriesInstances( + ApplicationContextInitializer.class)); + setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); + this.mainApplicationClass = deduceMainApplicationClass(); +} +``` + +## web环境检测 + +deduceWebEnvironment方法用于检测当前是否是web工程环境,检测的标准也很简单,classpath中必须同时存在下面这两个类: + +- javax.servlet.Servlet +- org.springframework.web.context.ConfigurableWebApplicationContext + +## ApplicationContextInitializer + +下一步便是检测应当使用哪些ApplicationContextInitializer,这货并不是spring-boot的专属,而是定义在context下,这东西是在喜闻乐见的refesh方法执行之前留给我们进行自定义初始化的钩子。典型的使用的场景是注册我们自己的属性来源、设置激活的profile。 + +在简单的web应用场景下(没有数据库/mybatis),共最终引入了下列的类: + +![ApplicationContextInitializer](images/ApplicationContextInitializer.png) + +来自于三个jar包: + +- spring-boot +- spring-boot-autoconfigure +- spring-beans + +## ApplicationListener + +这货是典型的观察者模式实现,类图: + +![ApplicationListener](images/ApplicationListener.png) + +在简单的web应用场景下,系统共初始化了这些监听器: + +![ApplicationListener](images/ApplicationListener_used.png) + +## SpringApplicationRunListener + +就像它长得那样,就是用来监听SpringApplication的run方法的监听器。看看这货用到了哪些实现类: + +![SpringApplicationRunListener](images/SpringApplicationRunListener.png) + +# run + +从这一节开始,就进入了SpringApplication的run方法的势力范围。整个方法的流程总结如下图: + +![SpringApplication.run](images/spring_application_run.png) + +## starting + +SpringApplicationRunListener其实起一个广播器的作用,将消息广播给ApplicationListener一节初始化的10个Listener中的某几个。 + +debug可以发现,对启动事件感兴趣的只有LoggingApplicationListener一个。 + + 当LoggingApplicationListener监听到启动事件时,所作的主要工作便是决定采用哪一个日志框架,其判断逻辑如下: + +- 如果系统变量`org.springframework.boot.logging.LoggingSystem`存在,那么由其决定。 + +- 依次检测classpath中这些类是否存在: + + ```java + ch.qos.logback.core.Appender; + org.apache.logging.log4j.core.impl.Log4jContextFactory; + java.util.logging.LogManager; + ``` + +## 环境准备 + +相关源码: + +```java +ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); +``` + +Spring里面的Environment到底是个什么东西,详细参考隔壁(Spring.md)Environment接口一节,总结来说,这货就是属性配置来源(比如系统变量)和profile的综合体。 + +### 属性来源 + +在web环境下共初始化了以下4个属性来源: + +- System.getProperties() +- System.getenv() +- servlet-context-init-params +- servlet-config-init-params + + +有意思的问题:此时servlet-context-init-params和servlet-config-init-params实际上是一个占位符,无法从这两个来源获得任何真实的属性,等到refresh方法执行时才会被真实的来源替换。 + +### profile配置 + +SpringApplication.configureProfiles方法: + +```java +protected void configureProfiles(ConfigurableEnvironment environment, String[] args) { + environment.getActiveProfiles(); // ensure they are initialized + // But these ones should go first (last wins in a property key clash) + // 默认空 + Set profiles = new LinkedHashSet(this.additionalProfiles); + profiles.addAll(Arrays.asList(environment.getActiveProfiles())); + environment.setActiveProfiles(profiles.toArray(new String[profiles.size()])); +} +``` + +active profile取自上一节中的属性来源,key为`spring.profiles.active`. + +## environmentPrepared + +### 配置文件加载 + +监听器ConfigFileApplicationListener负责spring-boot配置文件的加载,ConfigFileApplicationListener默认会从以下的位置搜索配置文件: + +1. classpath下的application.properties或application.yml +2. file:./下的application.properties或application.yml +3. classpath:config目录下的application.properties或application.yml +4. file:./config目录下的application.properties或application.yml + +此监听器是如何加载的?源码: + +```java +private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) { + List postProcessors = loadPostProcessors(); + postProcessors.add(this); + AnnotationAwareOrderComparator.sort(postProcessors); + for (EnvironmentPostProcessor postProcessor : postProcessors) { + postProcessor.postProcessEnvironment(event.getEnvironment(), + event.getSpringApplication()); + } +} +``` + +显然核心的加载操作是通过EnvironmentPostProcessor接口实现的,此接口允许我们在context刷新之前自定义配置加载,并且Spring推荐此接口的实现类同时实现Ordered接口。类图: + +![EnvironmentPostProcessor](images/EnvironmentPostProcessor.png) + +加上ConfigFileApplicationListener自己,spring-boot默认共初始化了三个加载器,其它两个是SpringApplicationJsonEnvironmentPostProcessor和CloudFoundryVcapEnvironmentPostProcessor,下面按照其优先级顺序进行说明。 + +#### SpringApplicationJsonEnvironmentPostProcessor + +尝试读取spring.application.json或SPRING_APPLICATION_JSON系统指定的json配置文件,从这里加载的配置具有最高的优先级,当然,默认是没有的。 + +#### CloudFoundryVcapEnvironmentPostProcessor + +从Cloud Foundry加载配置,这是什么东西问度娘。 + +#### ConfigFileApplicationListener + +这里就是加载配置文件加载一节所说的配置文件的过程。 + + + +TODO: 多profile配置文件加载 + + + + + diff --git a/note/spring-boot.uml b/note/spring-boot.uml new file mode 100644 index 0000000..70da408 --- /dev/null +++ b/note/spring-boot.uml @@ -0,0 +1,525 @@ + + + + + + + + + + +spring-boot +1 + +classes +qZA94hFdS0SLO4Ma0W4NXAAA +2 + +SpringApplicationRunListener +69VGSXSIBUW7p8ufeBl/9gAA + +/njh2Q/xeUGIf6Vw8nEdJAAA +1 + +clMaroon +$00B9FFFF +508 +96 +177 +59 +sdkNone +4NdjgA17bE2i/3g5wzvqpwAA + + +1 +SpringApplicationRunListener + + +<<interface>> + + +False + + + +False +4NdjgA17bE2i/3g5wzvqpwAA + + +4NdjgA17bE2i/3g5wzvqpwAA + + + + + +EnvironmentPostProcessor +69VGSXSIBUW7p8ufeBl/9gAA + +qm+rHb6SNkqLBiTGk7pzbwAA +11 + +clMaroon +$00B9FFFF +576 +68 +494 +59 +sdkNone +yKVxOflA2UaI4FHsb8TGJQAA + + +1 +EnvironmentPostProcessor + + +<<interface>> + + +False + + + +False +yKVxOflA2UaI4FHsb8TGJQAA + + +yKVxOflA2UaI4FHsb8TGJQAA + + + +clMaroon +$00B9FFFF +232 +236 +267 +43 +jCjCGZgJxk+c3RZE5Qq57gAA + + +1 +CloudFoundryVcapEnvironmentPostProcessor + + +False + + +False + + + +jCjCGZgJxk+c3RZE5Qq57gAA + + +jCjCGZgJxk+c3RZE5Qq57gAA + + +False +jCjCGZgJxk+c3RZE5Qq57gAA + + + +clMaroon +$00B9FFFF +619 +236 +288 +43 +W0cRRKVVBkCp+2Q9SH3UxgAA + + +1 +SpringApplicationJsonEnvironmentPostProcessor + + +False + + +False + + + +W0cRRKVVBkCp+2Q9SH3UxgAA + + +W0cRRKVVBkCp+2Q9SH3UxgAA + + +False +W0cRRKVVBkCp+2Q9SH3UxgAA + + + +clMaroon +$00B9FFFF +1027 +236 +173 +43 +Vw0ZAZppPEm7AlpNNggtGgAA + + +1 +ConfigFileApplicationListener + + +False + + +False + + + +Vw0ZAZppPEm7AlpNNggtGgAA + + +Vw0ZAZppPEm7AlpNNggtGgAA + + +False +Vw0ZAZppPEm7AlpNNggtGgAA + + + +clMaroon +$00B9FFFF +360 +68 +86 +59 +sdkNone +7GxYzq4AIkizabw6oPygqQAA + + +1 +Ordered + + +<<interface>> + + +False + + + +False +7GxYzq4AIkizabw6oPygqQAA + + +7GxYzq4AIkizabw6oPygqQAA + + + +clMaroon +$00B9FFFF +370,236;395,126 +4SbHHRophkuTs8QFsOr8fQAA ++k8WnQ0zkEC8VT9QQz9+OgAA +P6KG9fgsi06u+3WM6dvcmwAA + +False +1.5707963267949 +15 +4SbHHRophkuTs8QFsOr8fQAA + + +False +1.5707963267949 +30 +4SbHHRophkuTs8QFsOr8fQAA + + +False +-1.5707963267949 +15 +4SbHHRophkuTs8QFsOr8fQAA + + + +clMaroon +$00B9FFFF +425,236;739,126 +yYUBNggzPUG/3YZMjF72QQAA +lqFX6n755k6Hba7ST1jy1wAA +P6KG9fgsi06u+3WM6dvcmwAA + +False +1.5707963267949 +15 +yYUBNggzPUG/3YZMjF72QQAA + + +False +1.5707963267949 +30 +yYUBNggzPUG/3YZMjF72QQAA + + +False +-1.5707963267949 +15 +yYUBNggzPUG/3YZMjF72QQAA + + + +clMaroon +$00B9FFFF +715,236;445,116 +sdi/nrb10kCJ64hqARaXWAAA ++k8WnQ0zkEC8VT9QQz9+OgAA +E4P16TqYkUG2+qH+WaJtbwAA + +False +1.5707963267949 +15 +sdi/nrb10kCJ64hqARaXWAAA + + +False +1.5707963267949 +30 +sdi/nrb10kCJ64hqARaXWAAA + + +False +-1.5707963267949 +15 +sdi/nrb10kCJ64hqARaXWAAA + + + +clMaroon +$00B9FFFF +770,236;811,126 +fzumzPlz/0iBgpfrrvOhJQAA +lqFX6n755k6Hba7ST1jy1wAA +E4P16TqYkUG2+qH+WaJtbwAA + +False +1.5707963267949 +15 +fzumzPlz/0iBgpfrrvOhJQAA + + +False +1.5707963267949 +30 +fzumzPlz/0iBgpfrrvOhJQAA + + +False +-1.5707963267949 +15 +fzumzPlz/0iBgpfrrvOhJQAA + + + +clMaroon +$00B9FFFF +1027,238;445,107 +rG+WOaqFYkG6GXUZeUtgRAAA ++k8WnQ0zkEC8VT9QQz9+OgAA +3yHZR7jfDUqU/q5rcoobfgAA + +False +1.5707963267949 +15 +rG+WOaqFYkG6GXUZeUtgRAAA + + +False +1.5707963267949 +30 +rG+WOaqFYkG6GXUZeUtgRAAA + + +False +-1.5707963267949 +15 +rG+WOaqFYkG6GXUZeUtgRAAA + + + +clMaroon +$00B9FFFF +1075,236;875,126 +WvChNZk63UG/CiWuRWPIIwAA +lqFX6n755k6Hba7ST1jy1wAA +3yHZR7jfDUqU/q5rcoobfgAA + +False +1.5707963267949 +15 +WvChNZk63UG/CiWuRWPIIwAA + + +False +1.5707963267949 +30 +WvChNZk63UG/CiWuRWPIIwAA + + +False +-1.5707963267949 +15 +WvChNZk63UG/CiWuRWPIIwAA + + + + +12 + +SpringApplicationRunListener +69VGSXSIBUW7p8ufeBl/9gAA +3 +7pos0T+U7062k2pRb9krYQAA +vZkbhaFErUiZYOVv+9sHpwAA +030TeKKn3EuzD7i4zkelCQAA +1 + +void starting +4NdjgA17bE2i/3g5wzvqpwAA + + + +EnvironmentPostProcessor +69VGSXSIBUW7p8ufeBl/9gAA +3 +lqFX6n755k6Hba7ST1jy1wAA +XWuGtHMimECYIFoc8Id7dAAA +PuXfMWbnrkmQIc3bXK6+QwAA +3 +yYUBNggzPUG/3YZMjF72QQAA +fzumzPlz/0iBgpfrrvOhJQAA +WvChNZk63UG/CiWuRWPIIwAA +1 + +void postProcessEnvironment +yKVxOflA2UaI4FHsb8TGJQAA +2 + +ConfigurableEnvironment environment +bqCtvisSyEimrYDDokeTzAAA + + +SpringApplication application +bqCtvisSyEimrYDDokeTzAAA + + + + +CloudFoundryVcapEnvironmentPostProcessor +69VGSXSIBUW7p8ufeBl/9gAA +4 +P6KG9fgsi06u+3WM6dvcmwAA +fwYEhFbAhUW3txmAgc6qEgAA +XgsnnzJS3kOgNGcfKe2LEAAA +7HVPFqKJv0OTq86odgxmrAAA +2 +4SbHHRophkuTs8QFsOr8fQAA +yYUBNggzPUG/3YZMjF72QQAA + + +SpringApplicationJsonEnvironmentPostProcessor +69VGSXSIBUW7p8ufeBl/9gAA +4 +E4P16TqYkUG2+qH+WaJtbwAA +HAwEJWdWF0eLnSxluskdBAAA +QFvkquiBMUiXeeNJe0VS3QAA +P6UaJPEPAE6fmOFcWEi3iwAA +2 +sdi/nrb10kCJ64hqARaXWAAA +fzumzPlz/0iBgpfrrvOhJQAA + + +ConfigFileApplicationListener +69VGSXSIBUW7p8ufeBl/9gAA +4 +3yHZR7jfDUqU/q5rcoobfgAA +sdZbRO+xb0uDTPgTM6Lz+gAA +KMRwxm47bUyte4AAmIEBnAAA +Mvw1MqFvQUW8zi2QVAw1/wAA +2 +rG+WOaqFYkG6GXUZeUtgRAAA +WvChNZk63UG/CiWuRWPIIwAA + + +Ordered +69VGSXSIBUW7p8ufeBl/9gAA +3 ++k8WnQ0zkEC8VT9QQz9+OgAA +qEDeKjCCC021n71FXBamZgAA +MSfclWLhBEit3GHQJwf2+wAA +3 +4SbHHRophkuTs8QFsOr8fQAA +sdi/nrb10kCJ64hqARaXWAAA +rG+WOaqFYkG6GXUZeUtgRAAA +1 + +int getOrder +7GxYzq4AIkizabw6oPygqQAA + + + +69VGSXSIBUW7p8ufeBl/9gAA +jCjCGZgJxk+c3RZE5Qq57gAA +7GxYzq4AIkizabw6oPygqQAA +4 +64DFsXJ9JEeMUdpHsp+BugAA +y4EYtuEhC0ejkpIFceijzwAA +ZqEP5ycHu0aULbvZeaAu5wAA +QZ3NELwfEEOEgDHx4Ad/0AAA + + +69VGSXSIBUW7p8ufeBl/9gAA +jCjCGZgJxk+c3RZE5Qq57gAA +yKVxOflA2UaI4FHsb8TGJQAA +4 +eMyi+V4XhU+fT2JcvxNy4gAA +0mI/GAzW3U2+8VVBXIA5cgAA +MpO/Kw7VvkyRo4J+uIMuMQAA +Fu8EySBCT0+2rffldBqC+AAA + + +69VGSXSIBUW7p8ufeBl/9gAA +W0cRRKVVBkCp+2Q9SH3UxgAA +7GxYzq4AIkizabw6oPygqQAA +4 +3KueoVb0B0GJo5g0vX1NwAAA +cY+m06Faz0atMYj13QVUYAAA +yGAvTLcEFkCW/6F7LIIqzwAA +4nqMprd7tk6rMmDSKpyW7wAA + + +69VGSXSIBUW7p8ufeBl/9gAA +W0cRRKVVBkCp+2Q9SH3UxgAA +yKVxOflA2UaI4FHsb8TGJQAA +4 +HEBTMl5oFUifogqi0PAFVwAA +vvwUyIq6CEaFxWnsUq45aQAA +91vML38v0km69tVVLw1gOAAA +oJZMrIQ9EEieSvWnR8uABQAA + + +69VGSXSIBUW7p8ufeBl/9gAA +Vw0ZAZppPEm7AlpNNggtGgAA +7GxYzq4AIkizabw6oPygqQAA +4 +LM843eYjt0C96pmFrb1MDgAA +lxiHS0IIwEGS3Qvj/RsQWAAA +1evGo2PIFE2NlPSch++0xAAA +uabWPM723027n3XYs7lbtgAA + + +69VGSXSIBUW7p8ufeBl/9gAA +Vw0ZAZppPEm7AlpNNggtGgAA +yKVxOflA2UaI4FHsb8TGJQAA +4 +EmKsh5dzpEicXS/RjKzVjwAA +DfiAwKtWlEiz8tMZurmB4wAA +JG6V5rxzlEyDNR1rZluiMQAA +eQzpRi6zz02EOalo8lsBVgAA + + + + + diff --git a/note/spring-context.md b/note/spring-context.md index 585e539..8bc22f5 100644 --- a/note/spring-context.md +++ b/note/spring-context.md @@ -1,3 +1,140 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [开头](#%E5%BC%80%E5%A4%B4) +- [annotation-config](#annotation-config) + - [BeanPostProcessor注册](#beanpostprocessor%E6%B3%A8%E5%86%8C) + - [AnnotationAwareOrderComparator](#annotationawareordercomparator) + - [ContextAnnotationAutowireCandidateResolver](#contextannotationautowirecandidateresolver) + - [ConfigurationClassPostProcessor](#configurationclasspostprocessor) + - [AutowiredAnnotationBeanPostProcessor](#autowiredannotationbeanpostprocessor) + - [RequiredAnnotationBeanPostProcessor](#requiredannotationbeanpostprocessor) + - [CommonAnnotationBeanPostProcessor](#commonannotationbeanpostprocessor) + - [PersistenceAnnotationBeanPostProcessor](#persistenceannotationbeanpostprocessor) + - [EventListenerMethodProcessor](#eventlistenermethodprocessor) + - [DefaultEventListenerFactory](#defaulteventlistenerfactory) + - [逻辑关系整理](#%E9%80%BB%E8%BE%91%E5%85%B3%E7%B3%BB%E6%95%B4%E7%90%86) + - [运行](#%E8%BF%90%E8%A1%8C) + - [ConfigurationClassPostProcessor](#configurationclasspostprocessor-1) + - [postProcessBeanDefinitionRegistry](#postprocessbeandefinitionregistry) + - [BeanPostProcessor注册](#beanpostprocessor%E6%B3%A8%E5%86%8C-1) + - [ImportAwareBeanPostProcessor](#importawarebeanpostprocessor) + - [EnhancedConfigurationBeanPostProcessor](#enhancedconfigurationbeanpostprocessor) + - [类解析](#%E7%B1%BB%E8%A7%A3%E6%9E%90) + - [bean名字生成策略](#bean%E5%90%8D%E5%AD%97%E7%94%9F%E6%88%90%E7%AD%96%E7%95%A5) + - [postProcessBeanFactory](#postprocessbeanfactory) + - [AutowiredAnnotationBeanPostProcessor](#autowiredannotationbeanpostprocessor-1) + - [postProcessMergedBeanDefinition](#postprocessmergedbeandefinition) + - [入口](#%E5%85%A5%E5%8F%A3) + - [源码](#%E6%BA%90%E7%A0%81) + - [变量扫描](#%E5%8F%98%E9%87%8F%E6%89%AB%E6%8F%8F) + - [方法扫描](#%E6%96%B9%E6%B3%95%E6%89%AB%E6%8F%8F) + - [bridge方法](#bridge%E6%96%B9%E6%B3%95) + - [PropertyDescriptor](#propertydescriptor) + - [postProcessPropertyValues](#postprocesspropertyvalues) + - [入口](#%E5%85%A5%E5%8F%A3-1) + - [注入](#%E6%B3%A8%E5%85%A5) + - [Field注入](#field%E6%B3%A8%E5%85%A5) + - [方法注入](#%E6%96%B9%E6%B3%95%E6%B3%A8%E5%85%A5) + - [RequiredAnnotationBeanPostProcessor](#requiredannotationbeanpostprocessor-1) + - [postProcessMergedBeanDefinition](#postprocessmergedbeandefinition-1) + - [postProcessPropertyValues](#postprocesspropertyvalues-1) + - [结果缓存](#%E7%BB%93%E6%9E%9C%E7%BC%93%E5%AD%98) + - [PropertyDescriptor](#propertydescriptor-1) + - [测试](#%E6%B5%8B%E8%AF%95) + - [CommonAnnotationBeanPostProcessor](#commonannotationbeanpostprocessor-1) + - [postProcessMergedBeanDefinition](#postprocessmergedbeandefinition-2) + - [父类](#%E7%88%B6%E7%B1%BB) + - [子类](#%E5%AD%90%E7%B1%BB) + - [postProcessPropertyValues](#postprocesspropertyvalues-2) + - [postProcessBeforeInitialization](#postprocessbeforeinitialization) + - [postProcessBeforeDestruction](#postprocessbeforedestruction) + - [EventListenerMethodProcessor](#eventlistenermethodprocessor-1) + - [入口](#%E5%85%A5%E5%8F%A3-2) + - [源码](#%E6%BA%90%E7%A0%81-1) +- [component-scan](#component-scan) + - [初始化](#%E5%88%9D%E5%A7%8B%E5%8C%96) + - [use-default-filters](#use-default-filters) + - [扫描器:创建 & 初始化](#%E6%89%AB%E6%8F%8F%E5%99%A8%E5%88%9B%E5%BB%BA--%E5%88%9D%E5%A7%8B%E5%8C%96) + - [resource-pattern](#resource-pattern) + - [name-generator](#name-generator) + - [scope-resolver](#scope-resolver) + - [scoped-proxy](#scoped-proxy) + - [exclude-filter/include-filter](#exclude-filterinclude-filter) + - [annotation-config](#annotation-config-1) + - [扫描](#%E6%89%AB%E6%8F%8F) + - [逐包扫描/BeanDefinition解析](#%E9%80%90%E5%8C%85%E6%89%AB%E6%8F%8Fbeandefinition%E8%A7%A3%E6%9E%90) + - [@Scope解析](#scope%E8%A7%A3%E6%9E%90) + - [bean名字生成](#bean%E5%90%8D%E5%AD%97%E7%94%9F%E6%88%90) + - [根据注解](#%E6%A0%B9%E6%8D%AE%E6%B3%A8%E8%A7%A3) + - [默认策略](#%E9%BB%98%E8%AE%A4%E7%AD%96%E7%95%A5) + - [其它注解解析](#%E5%85%B6%E5%AE%83%E6%B3%A8%E8%A7%A3%E8%A7%A3%E6%9E%90) + - [冲突检测](#%E5%86%B2%E7%AA%81%E6%A3%80%E6%B5%8B) + - [代理生成](#%E4%BB%A3%E7%90%86%E7%94%9F%E6%88%90) + - [BeanDefinition注册](#beandefinition%E6%B3%A8%E5%86%8C) + - [Component注册](#component%E6%B3%A8%E5%86%8C) +- [property-override](#property-override) + - [作用](#%E4%BD%9C%E7%94%A8) + - [类图](#%E7%B1%BB%E5%9B%BE) + - [解析](#%E8%A7%A3%E6%9E%90) + - [properties-ref](#properties-ref) + - [order](#order) + - [ignore-resource-not-found](#ignore-resource-not-found) + - [ignore-unresolvable](#ignore-unresolvable) + - [local-override](#local-override) + - [BeanDefinition](#beandefinition) + - [运行](#%E8%BF%90%E8%A1%8C-1) + - [属性加载](#%E5%B1%9E%E6%80%A7%E5%8A%A0%E8%BD%BD) + - [属性转换](#%E5%B1%9E%E6%80%A7%E8%BD%AC%E6%8D%A2) + - [属性设置](#%E5%B1%9E%E6%80%A7%E8%AE%BE%E7%BD%AE) +- [property-placeholder](#property-placeholder) + - [解析](#%E8%A7%A3%E6%9E%90-1) + - [system-properties-mode](#system-properties-mode) + - [value-separator](#value-separator) + - [null-value](#null-value) + - [trim-values](#trim-values) + - [BeanDefinition](#beandefinition-1) + - [运行](#%E8%BF%90%E8%A1%8C-2) + - [处理](#%E5%A4%84%E7%90%86) +- [load-time-weaver & spring-configured](#load-time-weaver--spring-configured) + - [javaagent](#javaagent) + - [解析](#%E8%A7%A3%E6%9E%90-2) + - [LoadTimeWeaver](#loadtimeweaver) + - [LoadTimeWeaverBeanDefinitionParser](#loadtimeweaverbeandefinitionparser) + - [aspectj-weaving](#aspectj-weaving) + - [是否开启](#%E6%98%AF%E5%90%A6%E5%BC%80%E5%90%AF) + - [AspectJWeavingEnabler](#aspectjweavingenabler) + - [SpringConfiguredBeanDefinitionParser](#springconfiguredbeandefinitionparser) + - [切点(pointcut)](#%E5%88%87%E7%82%B9pointcut) + - [inConfigurableBean](#inconfigurablebean) + - [beanConstruction](#beanconstruction) + - [preConstructionCondition](#preconstructioncondition) + - [leastSpecificSuperTypeConstruction](#leastspecificsupertypeconstruction) + - [preConstructionConfiguration](#preconstructionconfiguration) + - [postConstructionCondition](#postconstructioncondition) + - [advise](#advise) + - [前置](#%E5%89%8D%E7%BD%AE) + - [运行](#%E8%BF%90%E8%A1%8C-3) + - [LoadTimeWeaverAware](#loadtimeweaveraware) + - [BeanClassLoaderAware](#beanclassloaderaware) + - [入口](#%E5%85%A5%E5%8F%A3-3) + - [setBeanClassLoader](#setbeanclassloader) + - [服务器agent](#%E6%9C%8D%E5%8A%A1%E5%99%A8agent) + - [Spring agent](#spring-agent) + - [反射](#%E5%8F%8D%E5%B0%84) + - [总结](#%E6%80%BB%E7%BB%93) + - [ClassFileTransformer](#classfiletransformer) + - [Aj](#aj) + - [缓存](#%E7%BC%93%E5%AD%98) + - [WeavingAdaptor初始化](#weavingadaptor%E5%88%9D%E5%A7%8B%E5%8C%96) + - [aop.xml](#aopxml) + - [解析](#%E8%A7%A3%E6%9E%90-3) + - [注册](#%E6%B3%A8%E5%86%8C) + - [总结](#%E6%80%BB%E7%BB%93-1) + + + # 开头 入口方法在BeanDefinitionParserDelegate.parseCustomElement: @@ -433,7 +570,7 @@ private static final Callback[] CALLBACKS = new Callback[] { ##### 入口 -其中前者首先被调用,时机是当BeanDefinition被合并(和父Bean),但是还没有用来创建Bean实例时。回顾下其调用入口: +其中前者首先被调用,时机是已创建Bean实例但还没有对实例执行初始化操作。回顾下其调用入口: AbstractAutowireCapableBeanFactory.doCreateBean(简略): diff --git a/note/spring-mvc.md b/note/spring-mvc.md index eba87cc..b217063 100644 --- a/note/spring-mvc.md +++ b/note/spring-mvc.md @@ -1,3 +1,73 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [初始化](#%E5%88%9D%E5%A7%8B%E5%8C%96) + - [容器初始化](#%E5%AE%B9%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96) + - [根容器查找](#%E6%A0%B9%E5%AE%B9%E5%99%A8%E6%9F%A5%E6%89%BE) + - [容器创建](#%E5%AE%B9%E5%99%A8%E5%88%9B%E5%BB%BA) + - [ApplicationContextInitializer](#applicationcontextinitializer) + - [配置解析](#%E9%85%8D%E7%BD%AE%E8%A7%A3%E6%9E%90) + - [注解驱动](#%E6%B3%A8%E8%A7%A3%E9%A9%B1%E5%8A%A8) + - [静态资源处理](#%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E5%A4%84%E7%90%86) + - [拦截器](#%E6%8B%A6%E6%88%AA%E5%99%A8) + - [视图](#%E8%A7%86%E5%9B%BE) + - [Scope/处理器注册](#scope%E5%A4%84%E7%90%86%E5%99%A8%E6%B3%A8%E5%86%8C) + - [MVC初始化](#mvc%E5%88%9D%E5%A7%8B%E5%8C%96) + - [文件上传支持](#%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E6%94%AF%E6%8C%81) + - [地区解析器](#%E5%9C%B0%E5%8C%BA%E8%A7%A3%E6%9E%90%E5%99%A8) + - [主题解析器](#%E4%B8%BB%E9%A2%98%E8%A7%A3%E6%9E%90%E5%99%A8) + - [HandlerMapping检查](#handlermapping%E6%A3%80%E6%9F%A5) + - [HandlerAdapter检查](#handleradapter%E6%A3%80%E6%9F%A5) + - [HandlerExceptionResolver检查](#handlerexceptionresolver%E6%A3%80%E6%9F%A5) + - [RequestToViewNameTranslator](#requesttoviewnametranslator) + - [ViewResolver检查](#viewresolver%E6%A3%80%E6%9F%A5) + - [FlashMapManager](#flashmapmanager) + - [HandlerMapping初始化](#handlermapping%E5%88%9D%E5%A7%8B%E5%8C%96) + - [RequestMappingHandlerMapping](#requestmappinghandlermapping) + - [跨域请求](#%E8%B7%A8%E5%9F%9F%E8%AF%B7%E6%B1%82) + - [拦截器初始化](#%E6%8B%A6%E6%88%AA%E5%99%A8%E5%88%9D%E5%A7%8B%E5%8C%96) + - [HandlerAdapter初始化](#handleradapter%E5%88%9D%E5%A7%8B%E5%8C%96) + - [@ControllerAdvice](#controlleradvice) + - [参数解析器](#%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90%E5%99%A8) + - [@InitBinder支持](#initbinder%E6%94%AF%E6%8C%81) + - [返回结果解析器](#%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E8%A7%A3%E6%9E%90%E5%99%A8) +- [请求响应](#%E8%AF%B7%E6%B1%82%E5%93%8D%E5%BA%94) + - [请求上下文](#%E8%AF%B7%E6%B1%82%E4%B8%8A%E4%B8%8B%E6%96%87) + - [请求分发](#%E8%AF%B7%E6%B1%82%E5%88%86%E5%8F%91) + - [处理器查找](#%E5%A4%84%E7%90%86%E5%99%A8%E6%9F%A5%E6%89%BE) + - [适配器查找](#%E9%80%82%E9%85%8D%E5%99%A8%E6%9F%A5%E6%89%BE) + - [请求处理](#%E8%AF%B7%E6%B1%82%E5%A4%84%E7%90%86) + - [Session同步](#session%E5%90%8C%E6%AD%A5) + - [参数解析](#%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90) + - [策略模式](#%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F) + - [自定义参数](#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%82%E6%95%B0) + - [参数名是从哪里来的](#%E5%8F%82%E6%95%B0%E5%90%8D%E6%98%AF%E4%BB%8E%E5%93%AA%E9%87%8C%E6%9D%A5%E7%9A%84) + - [Model](#model) + - [总结](#%E6%80%BB%E7%BB%93) + - [返回值解析](#%E8%BF%94%E5%9B%9E%E5%80%BC%E8%A7%A3%E6%9E%90) + - [视图渲染](#%E8%A7%86%E5%9B%BE%E6%B8%B2%E6%9F%93) + - [ModelAndView](#modelandview) + - [渲染](#%E6%B8%B2%E6%9F%93) + - [ViewResolver](#viewresolver) + - [View](#view) +- [拾遗](#%E6%8B%BE%E9%81%97) + - [@ResponseBody](#responsebody) + - [HttpMessageConverter](#httpmessageconverter) + - [自定义](#%E8%87%AA%E5%AE%9A%E4%B9%89) + - [默认](#%E9%BB%98%E8%AE%A4) + - [转换](#%E8%BD%AC%E6%8D%A2) + - [参数解析 & 结果转换](#%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90--%E7%BB%93%E6%9E%9C%E8%BD%AC%E6%8D%A2) + - ["纯"对象参数接收](#%E7%BA%AF%E5%AF%B9%E8%B1%A1%E5%8F%82%E6%95%B0%E6%8E%A5%E6%94%B6) + - [参数对象构造](#%E5%8F%82%E6%95%B0%E5%AF%B9%E8%B1%A1%E6%9E%84%E9%80%A0) + - [参数绑定](#%E5%8F%82%E6%95%B0%E7%BB%91%E5%AE%9A) + - [参数校验](#%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C) + - [JSR校验](#jsr%E6%A0%A1%E9%AA%8C) + - [自定义校验器](#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%A1%E9%AA%8C%E5%99%A8) + - [一个有意思的问题](#%E4%B8%80%E4%B8%AA%E6%9C%89%E6%84%8F%E6%80%9D%E7%9A%84%E9%97%AE%E9%A2%98) + + + # 初始化 spring-mvc的核心便是DispatcherServlet,所以初始化也是围绕其展开的。类图: @@ -1187,4 +1257,257 @@ HandlerMethodReturnValueHandler接口以及主要实现类如下: 从中也可以推测出我们可以把哪些类型的值(对象)直接"丢给"Spring。 -对于HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler来说,HttpMessageConverter像是两者手中用来实现功能的武器。 \ No newline at end of file +对于HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler来说,HttpMessageConverter像是两者手中用来实现功能的武器。 + +## "纯"对象参数接收 + +假设有如下这样的Controller: + +```java +@RequestMapping("/echoAgain") +public String echo(SimpleModel simpleModel, Model model) { + model.addAttribute("echo", "hello " + simpleModel.getName() + ", your age is " + simpleModel.getAge() + "."); + return "echo"; +} +``` + +经过测试可以发现,SimpleModel参数既可以接收get请求,也可以接收post请求。那么在这种情况下请求参数是被哪个参数解析器解析的呢,debug发现: ServletModelAttributeMethodProcessor: + +![ServletModelAttributeMethodProcessor](images/ServletModelAttributeMethodProcessor.jpg) + +核心的supportsParameter方法由父类ModelAttributeMethodProcessor实现: + +```java +@Override +public boolean supportsParameter(MethodParameter parameter) { + return (parameter.hasParameterAnnotation(ModelAttribute.class) || + (this.annotationNotRequired && !BeanUtils.isSimpleProperty(parameter.getParameterType()))); +} +``` + +可以看出,这里支持带有ModelAttribute注解或者是非基本类型的参数解析,同时annotationNotRequired必须设为false,即ModelAttribute注解不必存在,这里是在ServletModelAttributeMethodProcessor的构造器中进行控制的, +RequestMappingHandlerAdapter.getDefaultArgumentResolvers部分源码: + +```java +resolvers.add(new ServletModelAttributeMethodProcessor(false)); +``` + +此类的作用是对@ModelAttribute注解标注的参数进行解析,假设我们将Controller方法改写成: + +```java +@RequestMapping("/echoAgain") +public String echo(@ModelAttribute SimpleModel simpleModel, Model model) { + model.addAttribute("echo", "hello " + simpleModel.getName() + ", your age is " + simpleModel.getAge() + "."); + System.out.println(model.asMap().get("simpleModel")); + return "echo"; +} +``` + +首先,Spring会首先反射生成一个SimpleModel对象,之后将从request中获取的参数尝试设置到SimpleModel对象中去,最后将此对象放置到Model中(本质上就是一个Map),key就是simpleModel.下面我们来看一下具体的解析过程,整个过程可以分为 +以下三部分: + +### 参数对象构造 + +因为SimpleModel是一个对象类型,所以要想将参数注入到其中,第一步必然是先创建一个对象,创建的入口位于ModelAttributeMethodProcessor的resolveArgument方法,相关源码: + +```java +//name在这里便是simpleModel +String name = ModelFactory.getNameForParameter(parameter); +Object attribute = (mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) : + createAttribute(name, parameter, binderFactory, webRequest));//反射实例化 +``` + +ModelAndViewContainer是个什么东西呢,从名字就可以看出就,它是Spring MVC里两个重要概念Model和View的组合体,用来记录在请求响应过程中Model和View的变化,在这里可以简单理解为去Model中检查有没有叫simpleModel的属性已经存在。 + +### 参数绑定 + +这里使用到了DataBinder接口,按照注释的说明,此接口用以**向执行的对象中设置属性值**,就是这么简单,其继承体系如下图: + +![DataBinder](images/DataBinder.jpg) + +WebDataBinderFactory接口用以创建WebDataBinder对象,其继承体系如下图: + +![WebDataBinderFactory](images/WebDataBinderFactory.jpg) + +默认使用的是ServletRequestDataBinderFactory,创建了一个ExtendedServletRequestDataBinder对象: + +```java +@Override +protected ServletRequestDataBinder createBinderInstance(Object target, String objectName, NativeWebRequest request) { + return new ExtendedServletRequestDataBinder(target, objectName); +} +``` + +参数绑定的入口位于ModelAttributeMethodProcessor.resolveArgument方法,相关源码: + +```java +if (!mavContainer.isBindingDisabled(name)) { + bindRequestParameters(binder, webRequest); +} +``` + +接下来由ServletRequestDataBinder的bind方法完成,核心源码: + +```java +public void bind(ServletRequest request) { + MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request); + doBind(mpvs); +} +``` + +在ServletRequestParameterPropertyValues构造器中获取了Request中所有的属性对。doBind方法便是调用前面初始化的目标对象的setter方法进行参数设置的过程,不再展开。 + +### 参数校验 + +将我们的Controller方法改写为下面这种形式便可以启动Spring MVC的参数校验: + +```java +@RequestMapping("/echoAgain") +public String echo(@Validated SimpleModel simpleModel, Model model) { + model.addAttribute("echo", "hello " + simpleModel.getName() + ", your age is " + simpleModel.getAge() + "."); + System.out.println(model.asMap().get("simpleModel")); + return "echo"; +} +``` + +在这里@Validated注解可以用@Valid(javax)替换,前者是Spring对java校验标准的扩充,增加了校验组的支持。 +为什么参数校验要放到参数绑定后面进行说明呢,因为**@Validated和@valid注解不会影响Spring MVC参数解析的行为,被这两个注解标注的对象仍是由参数绑定一节提到的解析器进行解析。** + +当参数校验绑定之后,Spring MVC会尝试对参数进行校验,如果我们设置了校验注解。ModelAttributeMethodProcessor.resolveArgument方法相关源码: + +```java +validateIfApplicable(binder, parameter); + +protected void validateIfApplicable(WebDataBinder binder, MethodParameter methodParam) { + Annotation[] annotations = methodParam.getParameterAnnotations(); + for (Annotation ann : annotations) { + Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class); + if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) { + Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann)); + Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints}); + binder.validate(validationHints); + break; + } + } +} +``` + +DataBinder.validate: + +```java +public void validate(Object... validationHints) { + for (Validator validator : getValidators()) { + if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) { + ((SmartValidator) validator).validate(getTarget(), getBindingResult(), validationHints); + } else if (validator != null) { + validator.validate(getTarget(), getBindingResult()); + } + } +} +``` + +可见,具体的校验交给了`org.springframework.validation.Validator`实现,类图: + +![Validator](images/Validator.png) + +getValidators方法获取的实际上是DataBinder内部的validators字段: + +```java +private final List validators = new ArrayList(); +``` + +根据这里的校验器的来源可以分为以下两种情况。 + +#### JSR校验 + +需要引入hibernate-validator到classpath中,回顾最前面配置解析部分,配置: + +```xml + +``` + +会利用AnnotationDrivenBeanDefinitionParser进行相关的解析、初始化工作,正是在其parse方法完成了对JSR校验的支持。相关源码: + +```java +@Override +public BeanDefinition parse(Element element, ParserContext parserContext) { + RuntimeBeanReference validator = getValidator(element, source, parserContext); +} + +private RuntimeBeanReference getValidator(Element element, Object source, ParserContext parserContext) { + //mvc:annotation-driven配置支持validator属性 + if (element.hasAttribute("validator")) { + return new RuntimeBeanReference(element.getAttribute("validator")); + } else if (javaxValidationPresent) { + RootBeanDefinition validatorDef = new RootBeanDefinition( + "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean"); + validatorDef.setSource(source); + validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef); + parserContext.registerComponent(new BeanComponentDefinition(validatorDef, validatorName)); + return new RuntimeBeanReference(validatorName); + } else { + return null; + } +} +``` + +javaxValidationPresent的定义: + +```java +private static final boolean javaxValidationPresent = + ClassUtils.isPresent("javax.validation.Validator", AnnotationDrivenBeanDefinitionParser.class.getClassLoader()); +``` + + 实现了InitializingBean接口,所以afterPropertiesSet方法是其初始化的入口,具体的校验过程不再展开。 + 除此之外还有一个有意思的问题,就是上面提到的校验器是如何进入到DataBinder中去的呢?答案是WebDataBinderFactory创建DataBinder对象时会利用WebBindingInitializer对DataBinder进行初始化,正是在这里 + 将容器中存在的校验器设置到DataBinder中,至于WebBindingInitializer又是从哪里来的,不再探究了,否则这细节实在是太麻烦了,意义不大。 + +#### 自定义校验器 + +我们可以实现Spring提供的Validator接口,然后在Controller里边这样设置我们要是用的校验器: + +```java +@InitBinder +public void initBinder(DataBinder dataBinder) { + dataBinder.setValidator(new SimpleModelValidator()); + //如果有多个可以使用addValidators方法 +} +``` + +我们的Controller方法依然可以如此定义: + +```java +@RequestMapping("/echoAgain") +public String echo(@Validated SimpleModel simpleModel, Model model) { + return "echo"; +} +``` + +如果有错误,会直接返回400. + +#### 一个有意思的问题 + +如果我们把Controller方法这样定义会怎样? + +```java +@RequestMapping(value = "/echoAgain", method = RequestMethod.POST) +public String echo(@Validated @RequestBody SimpleModel simpleModel, Model model) {} +``` + +答案是@RequestBody注解先于@Validated注解起作用,这样既可以利用@RequestBody注解向Controller传递json串,同时又能够达到校验的目的。从源码的角度来说,这在很大程度上是一个顺序的问题: +RequestMappingHandlerAdapter.getDefaultArgumentResolvers相关源码: + +```java +resolvers.add(new ServletModelAttributeMethodProcessor(false)); +resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); +``` + +虽然ServletModelAttributeMethodProcessor位于RequestResponseBodyMethodProcessor之前,但构造器参数为false说明了此解析器必须要求参数被@ModelAttribute注解标注,其实在最后还有一个不需要注解的解析器被添加: + +```java +// Catch-all +resolvers.add(new ServletModelAttributeMethodProcessor(true)); +``` + +至此,真相大白。 \ No newline at end of file diff --git a/note/spring-mvc.uml b/note/spring-mvc.uml index 9fead32..5ccfb0d 100644 --- a/note/spring-mvc.uml +++ b/note/spring-mvc.uml @@ -13,7 +13,7 @@ classes OAE4p02Jq0OpklAf3brB/QAA -22 +25 DispatcherServlet f0Rg6JdVd0OMg3954zePZwAA @@ -4409,7 +4409,741 @@ -144 + +ServletModelAttributeMethodProcessor +f0Rg6JdVd0OMg3954zePZwAA + +UDJQm4b87ECfAwXFsnru6AAA +7 + +clMaroon +$00B9FFFF +264 +180 +298 +72 +sdkNone +peTc97n8EUu3mxXpQmi/OQAA + + +1 +HandlerMethodArgumentResolver + + +<<interface>> + + +False + + + +False +peTc97n8EUu3mxXpQmi/OQAA + + +peTc97n8EUu3mxXpQmi/OQAA + + + +clMaroon +$00B9FFFF +676 +180 +309 +72 +sdkNone +AxM/7rK/g0GLar9wkB2XXQAA + + +1 +HandlerMethodReturnValueHandler + + +<<interface>> + + +False + + + +False +AxM/7rK/g0GLar9wkB2XXQAA + + +AxM/7rK/g0GLar9wkB2XXQAA + + + +clMaroon +$00B9FFFF +526 +320 +195 +43 +ibXQqLx7ckSWOfZXsxBLjwAA + + +1 +ModelAttributeMethodProcessor + + +False + + +False + + + +ibXQqLx7ckSWOfZXsxBLjwAA + + +ibXQqLx7ckSWOfZXsxBLjwAA + + +False +ibXQqLx7ckSWOfZXsxBLjwAA + + + +clMaroon +$00B9FFFF +505 +428 +236 +43 +gjLsOeXqqkKj8QMxdihosQAA + + +1 +ServletModelAttributeMethodProcessor + + +False + + +False + + + +gjLsOeXqqkKj8QMxdihosQAA + + +gjLsOeXqqkKj8QMxdihosQAA + + +False +gjLsOeXqqkKj8QMxdihosQAA + + + +clMaroon +$00B9FFFF +588,320;472,251 +HhI8sYeMF0ys3M/9T2oTKwAA +rv9PEXadqEGCBS48x/re7gAA +fHdcTifBwkC3y1PUyVq6QAAA + +False +1.5707963267949 +15 +HhI8sYeMF0ys3M/9T2oTKwAA + + +False +1.5707963267949 +30 +HhI8sYeMF0ys3M/9T2oTKwAA + + +False +-1.5707963267949 +15 +HhI8sYeMF0ys3M/9T2oTKwAA + + + +clMaroon +$00B9FFFF +657,320;771,251 +pn6vT5w+mkOaR1MQs1QN/AAA +5aum4bXNxkeh3XjMFIYN2AAA +fHdcTifBwkC3y1PUyVq6QAAA + +False +1.5707963267949 +15 +pn6vT5w+mkOaR1MQs1QN/AAA + + +False +1.5707963267949 +30 +pn6vT5w+mkOaR1MQs1QN/AAA + + +False +-1.5707963267949 +15 +pn6vT5w+mkOaR1MQs1QN/AAA + + + +clMaroon +$00B9FFFF +622,428;623,362 +xIbzWrL0vUa1uG6adJVk5AAA +fHdcTifBwkC3y1PUyVq6QAAA +6TKNtNrhH06VHVI44sCUewAA + +False +1.5707963267949 +15 +xIbzWrL0vUa1uG6adJVk5AAA + + +False +1.5707963267949 +30 +xIbzWrL0vUa1uG6adJVk5AAA + + +False +-1.5707963267949 +15 +xIbzWrL0vUa1uG6adJVk5AAA + + + + + +DataBinder +f0Rg6JdVd0OMg3954zePZwAA + +esr4oSt9H0qUyMpIsMdqUgAA +11 + +clMaroon +$00B9FFFF +148 +76 +515 +85 +sdkNone +piQAW2SEpUe/rCvfoN3cQAAA + + +1 +PropertyEditorRegistry + + +<<interface>> + + +False + + + +False +piQAW2SEpUe/rCvfoN3cQAAA + + +piQAW2SEpUe/rCvfoN3cQAAA + + + +clMaroon +$00B9FFFF +700 +76 +474 +85 +sdkNone +BG8MYkfwdk2lyYL04Q1hSgAA + + +1 +TypeConverter + + +<<interface>> + + +False + + + +False +BG8MYkfwdk2lyYL04Q1hSgAA + + +BG8MYkfwdk2lyYL04Q1hSgAA + + + +clMaroon +$00B9FFFF +631 +228 +86 +43 +pNvR01Bc6kuV6Ut9BnX1bwAA + + +1 +DataBinder + + +False + + +False + + + +pNvR01Bc6kuV6Ut9BnX1bwAA + + +pNvR01Bc6kuV6Ut9BnX1bwAA + + +False +pNvR01Bc6kuV6Ut9BnX1bwAA + + + +clMaroon +$00B9FFFF +625 +308 +98 +43 +w2K7xvxiIUS65fEDoLk1mgAA + + +1 +WebDataBinder + + +False + + +False + + + +w2K7xvxiIUS65fEDoLk1mgAA + + +w2K7xvxiIUS65fEDoLk1mgAA + + +False +w2K7xvxiIUS65fEDoLk1mgAA + + + +clMaroon +$00B9FFFF +631,228;491,160 +2k6DnZODdEC7//zai45RMQAA +Z2csDvZeFUaOqeDewRMYygAA +eAOprjhxhkCW41wVvMB+eQAA + +False +1.5707963267949 +15 +2k6DnZODdEC7//zai45RMQAA + + +False +1.5707963267949 +30 +2k6DnZODdEC7//zai45RMQAA + + +False +-1.5707963267949 +15 +2k6DnZODdEC7//zai45RMQAA + + + +clMaroon +$00B9FFFF +716,228;852,160 +Zz0GMpvSaEuQxvqqCKvZvQAA +WShetbG+V0ycUL0v9FUi7AAA +eAOprjhxhkCW41wVvMB+eQAA + +False +1.5707963267949 +15 +Zz0GMpvSaEuQxvqqCKvZvQAA + + +False +1.5707963267949 +30 +Zz0GMpvSaEuQxvqqCKvZvQAA + + +False +-1.5707963267949 +15 +Zz0GMpvSaEuQxvqqCKvZvQAA + + + +clMaroon +$00B9FFFF +673,308;673,270 +5l972v0y/Ui0VCwW+tvW2wAA +eAOprjhxhkCW41wVvMB+eQAA +/kUDuaB74EeyUClxItcxlwAA + +False +1.5707963267949 +15 +5l972v0y/Ui0VCwW+tvW2wAA + + +False +1.5707963267949 +30 +5l972v0y/Ui0VCwW+tvW2wAA + + +False +-1.5707963267949 +15 +5l972v0y/Ui0VCwW+tvW2wAA + + + +clMaroon +$00B9FFFF +594 +388 +161 +43 +FLWL5G8Fy0eOR9NvFZcwTAAA + + +1 +ServletRequestDataBinder + + +False + + +False + + + +FLWL5G8Fy0eOR9NvFZcwTAAA + + +FLWL5G8Fy0eOR9NvFZcwTAAA + + +False +FLWL5G8Fy0eOR9NvFZcwTAAA + + + +clMaroon +$00B9FFFF +567 +468 +214 +43 +oh1ObkvL10yOHzlD5I/pmQAA + + +1 +ExtendedServletRequestDataBinder + + +False + + +False + + + +oh1ObkvL10yOHzlD5I/pmQAA + + +oh1ObkvL10yOHzlD5I/pmQAA + + +False +oh1ObkvL10yOHzlD5I/pmQAA + + + +clMaroon +$00B9FFFF +674,388;673,350 +6ZPEreowskq8Ll4G5xoiKwAA +/kUDuaB74EeyUClxItcxlwAA +d7VoCDk8hkSRLCj9PxUMAQAA + +False +1.5707963267949 +15 +6ZPEreowskq8Ll4G5xoiKwAA + + +False +1.5707963267949 +30 +6ZPEreowskq8Ll4G5xoiKwAA + + +False +-1.5707963267949 +15 +6ZPEreowskq8Ll4G5xoiKwAA + + + +clMaroon +$00B9FFFF +673,468;674,430 +FGAaCyp+t0aXHPA3PhpYRAAA +d7VoCDk8hkSRLCj9PxUMAQAA +q2B/MVi5VkuAa4yHdTEIkwAA + +False +1.5707963267949 +15 +FGAaCyp+t0aXHPA3PhpYRAAA + + +False +1.5707963267949 +30 +FGAaCyp+t0aXHPA3PhpYRAAA + + +False +-1.5707963267949 +15 +FGAaCyp+t0aXHPA3PhpYRAAA + + + + + +WebDataBinderFactory +f0Rg6JdVd0OMg3954zePZwAA + +Ua0UiXFEkkO5TOAMBHWKMAAA +7 + +clMaroon +$00B9FFFF +499 +64 +488 +59 +sdkNone +wKUl0IUMW0W9gNwI6CxlZAAA + + +1 +WebDataBinderFactory + + +<<interface>> + + +False + + + +False +wKUl0IUMW0W9gNwI6CxlZAAA + + +wKUl0IUMW0W9gNwI6CxlZAAA + + + +clMaroon +$00B9FFFF +665 +169 +157 +43 +9yrYPcKy+0uGnWPtCK2PsAAA + + +1 +DefaultDataBinderFactory + + +False + + +False + + + +9yrYPcKy+0uGnWPtCK2PsAAA + + +9yrYPcKy+0uGnWPtCK2PsAAA + + +False +9yrYPcKy+0uGnWPtCK2PsAAA + + + +clMaroon +$00B9FFFF +657 +258 +172 +43 +yhK7vbyjL06s/ziF6GC88gAA + + +1 +InitBinderDataBinderFactory + + +False + + +False + + + +yhK7vbyjL06s/ziF6GC88gAA + + +yhK7vbyjL06s/ziF6GC88gAA + + +False +yhK7vbyjL06s/ziF6GC88gAA + + + +clMaroon +$00B9FFFF +641 +347 +204 +43 +UyKFirHXNU2r9RKRIB0gCwAA + + +1 +ServletRequestDataBinderFactory + + +False + + +False + + + +UyKFirHXNU2r9RKRIB0gCwAA + + +UyKFirHXNU2r9RKRIB0gCwAA + + +False +UyKFirHXNU2r9RKRIB0gCwAA + + + +clMaroon +$00B9FFFF +743,169;742,122 +S9JMEFMFmkO9hRPIOTyLkQAA +Tbj+QFoOYEiOy3zrbRgqcQAA +FcxNSNGHoESYUN+VRFn/KgAA + +False +1.5707963267949 +15 +S9JMEFMFmkO9hRPIOTyLkQAA + + +False +1.5707963267949 +30 +S9JMEFMFmkO9hRPIOTyLkQAA + + +False +-1.5707963267949 +15 +S9JMEFMFmkO9hRPIOTyLkQAA + + + +clMaroon +$00B9FFFF +742,258;743,211 +V/WkItcHYkSPJfLrj/d9zwAA +FcxNSNGHoESYUN+VRFn/KgAA +meF/RUQ8a0mjB1ESPqnnUAAA + +False +1.5707963267949 +15 +V/WkItcHYkSPJfLrj/d9zwAA + + +False +1.5707963267949 +30 +V/WkItcHYkSPJfLrj/d9zwAA + + +False +-1.5707963267949 +15 +V/WkItcHYkSPJfLrj/d9zwAA + + + +clMaroon +$00B9FFFF +742,347;742,300 +cqQ8qAvBDEeKhtLtVdPI0AAA +meF/RUQ8a0mjB1ESPqnnUAAA +ffq1tTCxjkay45CSLHGA3wAA + +False +1.5707963267949 +15 +cqQ8qAvBDEeKhtLtVdPI0AAA + + +False +1.5707963267949 +30 +cqQ8qAvBDEeKhtLtVdPI0AAA + + +False +-1.5707963267949 +15 +cqQ8qAvBDEeKhtLtVdPI0AAA + + + + +167 Servlet f0Rg6JdVd0OMg3954zePZwAA @@ -5708,17 +6442,21 @@ HandlerMethodArgumentResolver f0Rg6JdVd0OMg3954zePZwAA -6 +9 vWfojbrAMUmYsvomk6kLvQAA bI+cXd6Kc0yBYNCAY5fPpgAA Edr2pVCtqk6UsuvdLkTqEQAA LLn27gmaHEKAiZZT+MLONwAA 8N5RHGxfE0CjfGJ2yn9G+QAA cpvr6q+p8EexEbvLlFbXYgAA -3 +rv9PEXadqEGCBS48x/re7gAA +YIXUuCCHyEqo+uZGf/4WPQAA +ngAwPD+33UKpwqHhnEEK/wAA +4 sQQIFHG3aE2xOYT+cKjRdwAA 5SVpxR1180CZSECIlxOBIAAA NaM3heUPo0q20AUHwMJ3CwAA +HhI8sYeMF0ys3M/9T2oTKwAA 2 boolean supportsParameter @@ -5742,17 +6480,21 @@ HandlerMethodReturnValueHandler f0Rg6JdVd0OMg3954zePZwAA -6 +9 koFyJoNyJUaSI1YEJQYVjQAA pssrew/SVkeC8yF9kdNfHwAA E+BRXJh8HUeWzAoIR0H+XwAA Xk8eOEILgU6VT93LOCT5kQAA nqLfmK28q0mqqD9Umo+gPAAA AMAv97kycUK0nGzgCQ3kQgAA -3 +5aum4bXNxkeh3XjMFIYN2AAA +Aj0bbg4KYE6Jtpw6W0leswAA +bDHFjw0JXEG3VVmRirexnQAA +4 mEb/Cv39rEi2aR36ilmqjQAA K+7PNUoTiUabFxJ2oKgHVQAA 3BIm9nAI6UC51JF8+fP6XAAA +pn6vT5w+mkOaR1MQs1QN/AAA 2 boolean supportsReturnType @@ -6743,6 +7485,369 @@ +0Nw5xsKokqDkrsMbESbRgAA xuTQv6cGO02PQeK9RkRpDwAA + +ModelAttributeMethodProcessor +f0Rg6JdVd0OMg3954zePZwAA +4 +fHdcTifBwkC3y1PUyVq6QAAA +Bzyy0AttQ0ejvr94QbZ9OAAA +3SEBCl7JyU6hZJua7KMhgQAA +JLPdPSuraUOowDy6WUdGtgAA +2 +HhI8sYeMF0ys3M/9T2oTKwAA +pn6vT5w+mkOaR1MQs1QN/AAA +1 +xIbzWrL0vUa1uG6adJVk5AAA + + +ServletModelAttributeMethodProcessor +f0Rg6JdVd0OMg3954zePZwAA +4 +6TKNtNrhH06VHVI44sCUewAA +7RpMlA7t6UyWY2IsslzXOQAA +yMn4xSD1qEmjzQvI+iPkwAAA +6X889fII70WGx2Ah9hgiswAA +1 +xIbzWrL0vUa1uG6adJVk5AAA + + +f0Rg6JdVd0OMg3954zePZwAA +ibXQqLx7ckSWOfZXsxBLjwAA +peTc97n8EUu3mxXpQmi/OQAA +4 +fn2T6Y7SXEuqh7G8Lr2x0QAA +WX2dmI75IkmcteUji6UVjwAA +q6NhrPu8q0y2y389l10nDQAA +PeFoagF5IkSp9Zawyno52wAA + + +f0Rg6JdVd0OMg3954zePZwAA +ibXQqLx7ckSWOfZXsxBLjwAA +AxM/7rK/g0GLar9wkB2XXQAA +4 ++140xJ7iT0CXzJ2NXqrV0AAA +35jyvaS4CUCwi4QnNWurIwAA +FPnOefJKG0uZUOwJdwe9sAAA +tnpPbeksYEqsQP9BFdWRsQAA + + +f0Rg6JdVd0OMg3954zePZwAA +gjLsOeXqqkKj8QMxdihosQAA +ibXQqLx7ckSWOfZXsxBLjwAA +4 +SPO5vrS66U+/OiwocIcGPgAA +Y9NHEXK2NkCj6nnMGPdk3QAA +nDMxMrRsj0atX22tptcvuQAA +nOXi52n3D0Sx0OqmVZEclAAA + + +PropertyEditorRegistry +f0Rg6JdVd0OMg3954zePZwAA +3 +Z2csDvZeFUaOqeDewRMYygAA +uSYe0x2/pkCJGN2pu/tTBgAA +bJQyy44NFUi8br7SG9rY1QAA +1 +2k6DnZODdEC7//zai45RMQAA +3 + +void registerCustomEditor +piQAW2SEpUe/rCvfoN3cQAAA +2 + +Class<?> requiredType +GezSC47ndUOhtqnFK4z8bQAA + + +PropertyEditor propertyEditor +GezSC47ndUOhtqnFK4z8bQAA + + + +void registerCustomEditor +piQAW2SEpUe/rCvfoN3cQAAA +3 + +Class<?> requiredType +/tNjM7s7jUORx0Z8Z4s23wAA + + +String propertyPath +/tNjM7s7jUORx0Z8Z4s23wAA + + +PropertyEditor propertyEditor +/tNjM7s7jUORx0Z8Z4s23wAA + + + +PropertyEditor findCustomEditor +piQAW2SEpUe/rCvfoN3cQAAA +2 + +Class<?> requiredType +bh02mP0a+EysXtTc0veqMQAA + + +String propertyPath +bh02mP0a+EysXtTc0veqMQAA + + + + +TypeConverter +f0Rg6JdVd0OMg3954zePZwAA +3 +WShetbG+V0ycUL0v9FUi7AAA +aY944ttpX0qD1WGxoerjLQAA +aMMdGgg/FECgTYtxEtJVTgAA +1 +Zz0GMpvSaEuQxvqqCKvZvQAA +3 + +T convertIfNecessary +BG8MYkfwdk2lyYL04Q1hSgAA +2 + +Object value +svKU7cw/zECUH3cCN+U2PwAA + + +Class<T> requiredType +svKU7cw/zECUH3cCN+U2PwAA + + + +T convertIfNecessary +BG8MYkfwdk2lyYL04Q1hSgAA +3 + +Object value +kG1lMLPdUEaLoSQVSdf+RgAA + + +Class<T> requiredType +kG1lMLPdUEaLoSQVSdf+RgAA + + +MethodParameter methodParam +kG1lMLPdUEaLoSQVSdf+RgAA + + + +T convertIfNecessary +BG8MYkfwdk2lyYL04Q1hSgAA +3 + +Object value +PZt6FSgC/kKN+uGVCtiplQAA + + +Class<T> requiredType +PZt6FSgC/kKN+uGVCtiplQAA + + +Field field +PZt6FSgC/kKN+uGVCtiplQAA + + + + +DataBinder +f0Rg6JdVd0OMg3954zePZwAA +4 +eAOprjhxhkCW41wVvMB+eQAA +GqSR/b0XnU6RNV1cOY/HsgAA +K4NKmVLEQU+1BmmPCljhZgAA +g9PsZnK2ZkmjMsqNkeqz3wAA +2 +2k6DnZODdEC7//zai45RMQAA +Zz0GMpvSaEuQxvqqCKvZvQAA +1 +5l972v0y/Ui0VCwW+tvW2wAA + + +WebDataBinder +f0Rg6JdVd0OMg3954zePZwAA +4 +/kUDuaB74EeyUClxItcxlwAA +v2qpV03TrEu1AoWAxMeeowAA +g+whx8rtW0OyuHUD9EX5GwAA +PhwqhkdCJkygUcfLlkQFdwAA +1 +5l972v0y/Ui0VCwW+tvW2wAA +1 +6ZPEreowskq8Ll4G5xoiKwAA + + +f0Rg6JdVd0OMg3954zePZwAA +pNvR01Bc6kuV6Ut9BnX1bwAA +piQAW2SEpUe/rCvfoN3cQAAA +4 +/2zoSbgWpkWDgccWDiheHwAA +YgMXBNJJlkGYzz+yFOUwEwAA +avCAiHj3d0aJHKmUO87z+wAA +ODFHxfo+PU+CeP8OXghSSAAA + + +f0Rg6JdVd0OMg3954zePZwAA +pNvR01Bc6kuV6Ut9BnX1bwAA +BG8MYkfwdk2lyYL04Q1hSgAA +4 +MwlCdWYFi0ePKP3HTrKhlQAA +Tp9JHWeMDUyZxTxQWBdFHwAA +esjh4TFqakisvvFn2deZogAA +CHh/cRqOgkChybpBtDl6fwAA + + +f0Rg6JdVd0OMg3954zePZwAA +w2K7xvxiIUS65fEDoLk1mgAA +pNvR01Bc6kuV6Ut9BnX1bwAA +4 +7U1tY2J5/0ulGCFXJIT1YQAA +OaOBCTeOQkyVsvAiBl9hRgAA +kOa9VXrUdUmHNfsa2j+OPAAA +xK2Bqmyjpku14kGawAllXQAA + + +WebDataBinderFactory +f0Rg6JdVd0OMg3954zePZwAA +3 +Tbj+QFoOYEiOy3zrbRgqcQAA +WH9H5W0q4kqq+krzj+YVkgAA +5rudIgzHZ0qmUU1u93nykwAA +1 +S9JMEFMFmkO9hRPIOTyLkQAA +1 + +WebDataBinder createBinder +wKUl0IUMW0W9gNwI6CxlZAAA +3 + +NativeWebRequest webRequest +AYBnIu51aU26lFRBaIBUtgAA + + +Object target +AYBnIu51aU26lFRBaIBUtgAA + + +String objectName +AYBnIu51aU26lFRBaIBUtgAA + + + + +DefaultDataBinderFactory +f0Rg6JdVd0OMg3954zePZwAA +4 +FcxNSNGHoESYUN+VRFn/KgAA +DeuCpSWPEU2bb3Kx0eaOQgAA +kijz2GvMAEe2mXKRzwyzBwAA +4sZC5XdsxUOCClK1juidqgAA +1 +S9JMEFMFmkO9hRPIOTyLkQAA +1 +V/WkItcHYkSPJfLrj/d9zwAA + + +InitBinderDataBinderFactory +f0Rg6JdVd0OMg3954zePZwAA +4 +meF/RUQ8a0mjB1ESPqnnUAAA +l0BvVXUc/Ee6mFIrlSiGwgAA +eXH8QAYJDUCrHbjPpSxUOQAA +riW28AFawEy0CCyGSSkEgwAA +1 +V/WkItcHYkSPJfLrj/d9zwAA +1 +cqQ8qAvBDEeKhtLtVdPI0AAA + + +ServletRequestDataBinderFactory +f0Rg6JdVd0OMg3954zePZwAA +4 +ffq1tTCxjkay45CSLHGA3wAA +p+0tX/sdJkm93S80oDOUWgAA +9OvDeRC3RE6u5KpmPpgwTwAA +Y2swPHjQe0+fanxGnemcMgAA +1 +cqQ8qAvBDEeKhtLtVdPI0AAA + + +f0Rg6JdVd0OMg3954zePZwAA +9yrYPcKy+0uGnWPtCK2PsAAA +wKUl0IUMW0W9gNwI6CxlZAAA +4 +Xir3C8L9gkCy1dd0PnuAxQAA +K3piFQpQvUa2kdlGDEUG9wAA +TFKLU0/pxU28OaQGhsm0SQAA +p6H9W9mVn0WPhf8zPQ0BiwAA + + +f0Rg6JdVd0OMg3954zePZwAA +yhK7vbyjL06s/ziF6GC88gAA +9yrYPcKy+0uGnWPtCK2PsAAA +4 +ZOppfJGxpUSZ60kZeq8oJwAA +xz+GA41cjk2cZIqIBNzfkQAA +ogU9acFPwky4Hn1MA8r73gAA +zd6Y6eqOWEyEVLZJwXRHWgAA + + +f0Rg6JdVd0OMg3954zePZwAA +UyKFirHXNU2r9RKRIB0gCwAA +yhK7vbyjL06s/ziF6GC88gAA +4 +BIgZlgdMCkOLHle53lJ3HgAA +hqvRHCyNxkSGca0vgtnDmwAA +a2+r8o0ZYkydMtHAbwSN1QAA +fAc10pz5xkqa6ezaInKUsAAA + + +ServletRequestDataBinder +f0Rg6JdVd0OMg3954zePZwAA +4 +d7VoCDk8hkSRLCj9PxUMAQAA +sb0HToHNi0euYFE/Wre4hgAA +wCmdWLGPdkGa7eBPbqxyfQAA +OWOxudkHeEmvxVzWM0VSTgAA +1 +6ZPEreowskq8Ll4G5xoiKwAA +1 +FGAaCyp+t0aXHPA3PhpYRAAA + + +ExtendedServletRequestDataBinder +f0Rg6JdVd0OMg3954zePZwAA +4 +q2B/MVi5VkuAa4yHdTEIkwAA +RvaR3Tvan02R52PQQ4G+0gAA +I9JQBM42GU+94UnDDDlTGwAA +9O2N0C0kuUOIpZfK7/jY4QAA +1 +FGAaCyp+t0aXHPA3PhpYRAAA + + +f0Rg6JdVd0OMg3954zePZwAA +FLWL5G8Fy0eOR9NvFZcwTAAA +w2K7xvxiIUS65fEDoLk1mgAA +4 +Uu74J7mX0EykJEYw29gZ8AAA +1EqmNZS72UqwAWcJDXdLQAAA +rXgkNx3FIEG0WuD1t60gdwAA +RBnWgG/asEqwYjyqDXQMbQAA + + +f0Rg6JdVd0OMg3954zePZwAA +oh1ObkvL10yOHzlD5I/pmQAA +FLWL5G8Fy0eOR9NvFZcwTAAA +4 +D+hWN0fL9UmCSYMnAbizbwAA +x6kM1IaD1UKuEeu7UX8KaAAA +cpqJUJuOCU2skrsbzSyyXwAA +BdegGiyk8EG9WkTaCN/HzAAA + diff --git a/note/spring-task.md b/note/spring-task.md index 4212b0c..f84e8e1 100644 --- a/note/spring-task.md +++ b/note/spring-task.md @@ -1,3 +1,27 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [开头](#%E5%BC%80%E5%A4%B4) +- [定时器](#%E5%AE%9A%E6%97%B6%E5%99%A8) + - [用法](#%E7%94%A8%E6%B3%95) + - [解析](#%E8%A7%A3%E6%9E%90) + - [注册](#%E6%B3%A8%E5%86%8C) + - [scheduler](#scheduler) + - [scheduled-tasks](#scheduled-tasks) + - [调度执行](#%E8%B0%83%E5%BA%A6%E6%89%A7%E8%A1%8C) + - [scheduler初始化](#scheduler%E5%88%9D%E5%A7%8B%E5%8C%96) + - [任务调度](#%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6) + - [Trigger](#trigger) + - [Cron解析](#cron%E8%A7%A3%E6%9E%90) + - [调度](#%E8%B0%83%E5%BA%A6) + - [总结](#%E6%80%BB%E7%BB%93) +- [异步执行](#%E5%BC%82%E6%AD%A5%E6%89%A7%E8%A1%8C) + - [配置](#%E9%85%8D%E7%BD%AE) + - [原理](#%E5%8E%9F%E7%90%86) + + + # 开头 从功能上来说,spring-task这个组件主要包括了两个/两种功能: diff --git a/note/spring-transaction.md b/note/spring-transaction.md index c6d59d8..296635e 100644 --- a/note/spring-transaction.md +++ b/note/spring-transaction.md @@ -1,3 +1,37 @@ + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [配置](#%E9%85%8D%E7%BD%AE) +- [解析](#%E8%A7%A3%E6%9E%90) + - [TransactionalEventListener](#transactionaleventlistener) + - [主要组件注册](#%E4%B8%BB%E8%A6%81%E7%BB%84%E4%BB%B6%E6%B3%A8%E5%86%8C) + - [代理类生成](#%E4%BB%A3%E7%90%86%E7%B1%BB%E7%94%9F%E6%88%90) + - [Advisor寻找](#advisor%E5%AF%BB%E6%89%BE) +- [运行](#%E8%BF%90%E8%A1%8C) + - [调用链生成](#%E8%B0%83%E7%94%A8%E9%93%BE%E7%94%9F%E6%88%90) + - [调用链调用](#%E8%B0%83%E7%94%A8%E9%93%BE%E8%B0%83%E7%94%A8) + - [TransactionInterceptor](#transactioninterceptor) + - [事务管理器](#%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E5%99%A8) + - [DataSource](#datasource) + - [事务开启](#%E4%BA%8B%E5%8A%A1%E5%BC%80%E5%90%AF) + - [是否已存在事务](#%E6%98%AF%E5%90%A6%E5%B7%B2%E5%AD%98%E5%9C%A8%E4%BA%8B%E5%8A%A1) + - [事务已存在](#%E4%BA%8B%E5%8A%A1%E5%B7%B2%E5%AD%98%E5%9C%A8) + - [PROPAGATION_NEVER](#propagation_never) + - [PROPAGATION_NOT_SUPPORTED](#propagation_not_supported) + - [事务挂起](#%E4%BA%8B%E5%8A%A1%E6%8C%82%E8%B5%B7) + - [PROPAGATION_REQUIRES_NEW](#propagation_requires_new) + - [PROPAGATION_NESTED](#propagation_nested) + - [debug环境搭建](#debug%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA) + - [事务对象](#%E4%BA%8B%E5%8A%A1%E5%AF%B9%E8%B1%A1) + - [Savepoint](#savepoint) + - [其它](#%E5%85%B6%E5%AE%83) + - [事务创建](#%E4%BA%8B%E5%8A%A1%E5%88%9B%E5%BB%BA) + - [事务提交 & 回滚](#%E4%BA%8B%E5%8A%A1%E6%8F%90%E4%BA%A4--%E5%9B%9E%E6%BB%9A) +- [总结](#%E6%80%BB%E7%BB%93) + + + # 配置 以最简单的jdbc事务为例: diff --git a/pom.xml b/pom.xml index 26cdbbf..adb42cd 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ http://maven.apache.org UTF-8 - 4.3.2.RELEASE + 4.3.18.RELEASE @@ -82,11 +82,35 @@ 1.3 + + org.codehaus.jackson + jackson-mapper-asl + 1.9.13 + + + com.fasterxml.jackson.core + jackson-databind + 2.10.0.pr1 + + mysql mysql-connector-java 5.1.20 + + + cglib + cglib + 3.2.5 + + + + org.hibernate.validator + hibernate-validator + 6.1.0.Final + + @@ -95,6 +119,7 @@ org.apache.maven.plugins maven-compiler-plugin + false 1.8 1.8 diff --git a/src/main/java/aop/Bootstrap.java b/src/main/java/aop/Bootstrap.java new file mode 100644 index 0000000..9bf64b0 --- /dev/null +++ b/src/main/java/aop/Bootstrap.java @@ -0,0 +1,19 @@ +package aop; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * AOP测试启动类. + * + * @author skywalker + */ +public class Bootstrap { + + public static void main(String[] args) { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml"); + SimpleAopBean bean = context.getBean(SimpleAopBean.class); + bean.testB(); + System.out.println(bean.getClass().getSimpleName()); + } + +} diff --git a/src/main/java/aop/SimpleAopBean.java b/src/main/java/aop/SimpleAopBean.java new file mode 100644 index 0000000..7c002a9 --- /dev/null +++ b/src/main/java/aop/SimpleAopBean.java @@ -0,0 +1,24 @@ +package aop; + +import org.springframework.aop.framework.AopContext; + +/** + * @author skywalker + */ +public class SimpleAopBean { + + public void boo() { + System.out.println("testA执行"); + testB(); + } + + public void testB() { + System.out.println("testB执行"); + ((SimpleAopBean) AopContext.currentProxy()).testC(); + } + + public void testC() { + System.out.println("testC执行"); + } + +} diff --git a/src/main/java/aop/SimpleChildAopBean.java b/src/main/java/aop/SimpleChildAopBean.java new file mode 100644 index 0000000..8b5edc9 --- /dev/null +++ b/src/main/java/aop/SimpleChildAopBean.java @@ -0,0 +1,12 @@ +package aop; + +/** + * @author skywalker + */ +public class SimpleChildAopBean extends SimpleAopBean { + + @Override + public void testC() { + System.out.println("child testC"); + } +} diff --git a/src/main/java/aop/SimpleMethodInterceptor.java b/src/main/java/aop/SimpleMethodInterceptor.java new file mode 100644 index 0000000..7c161a5 --- /dev/null +++ b/src/main/java/aop/SimpleMethodInterceptor.java @@ -0,0 +1,17 @@ +package aop; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +/** + * @author skywalker + */ +public class SimpleMethodInterceptor implements MethodInterceptor { + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + System.out.println("SimpleMethodInterceptor被调用: " + invocation.getMethod().getName()); + return invocation.proceed(); + } + +} diff --git a/src/main/java/controller/SimpleController.java b/src/main/java/controller/SimpleController.java index b7cd6c3..97a525f 100644 --- a/src/main/java/controller/SimpleController.java +++ b/src/main/java/controller/SimpleController.java @@ -1,8 +1,20 @@ package controller; +import model.SimpleModel; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.validation.BindingResult; +import org.springframework.validation.DataBinder; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.util.Set; /** * 简单的Spring {@link org.springframework.stereotype.Controller}. @@ -12,10 +24,43 @@ @Controller public class SimpleController { + private Validator validator; + + @InitBinder + public void initBinder(DataBinder dataBinder) { + //dataBinder.setValidator(new SimpleModelValidator()); + //dataBinder.addValidators(new SimpleModelValidator()); + } + + @PostConstruct + public void initValidator() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + this.validator = factory.getValidator(); + } + @RequestMapping("/echo") - public String echo(String name, Model model) { + public String echo(@RequestParam("name") String name, Model model, HttpServletRequest request) throws InterruptedException { model.addAttribute("echo", "hello " + name); return "echo"; } + @RequestMapping(value = "/echoAgain", method = RequestMethod.POST) + public String echo(@RequestBody SimpleModel simpleModel, BindingResult bindingResult, Model model) { + + Set> result = validator.validate(simpleModel); + for (ConstraintViolation r : result) { + System.out.println("错误消息: " + r.getMessage()); + } + + String hello; + if (bindingResult.hasErrors()) { + hello = "Ops, error!"; + } else { + hello = "hello " + simpleModel.getName() + ", your age is " + simpleModel.getAge() + "."; + } + model.addAttribute("echo", hello); + System.out.println(simpleModel); + return "echo"; + } + } diff --git a/src/main/java/model/SimpleModel.java b/src/main/java/model/SimpleModel.java new file mode 100644 index 0000000..94ea6ab --- /dev/null +++ b/src/main/java/model/SimpleModel.java @@ -0,0 +1,53 @@ +package model; + +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.Max; +import java.util.Date; + +/** + * 简单的model. + * + * @author skywalker + */ +public class SimpleModel { + + private String name; + @Max(value = 90, message = "年龄最大不能超过90") + private Integer age; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date date; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + @Override + public String toString() { + return "SimpleModel{" + + "name='" + name + '\'' + + ", age=" + age + + ", date='" + date + '\'' + + '}'; + } +} diff --git a/src/main/java/validator/SimpleModelValidator.java b/src/main/java/validator/SimpleModelValidator.java new file mode 100644 index 0000000..53bd23b --- /dev/null +++ b/src/main/java/validator/SimpleModelValidator.java @@ -0,0 +1,28 @@ +package validator; + +import model.SimpleModel; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +/** + * 自定义Spring校验器. + * + * @author skywalker + */ +public class SimpleModelValidator implements Validator { + + @Override + public boolean supports(Class clazz) { + return (clazz == SimpleModel.class); + } + + @Override + public void validate(Object target, Errors errors) { + SimpleModel simpleModel = (SimpleModel) target; + Integer age = simpleModel.getAge(); + if (age == null || age < 1 || age > 200) { + errors.reject("100", "年龄不合法"); + } + } + +} diff --git a/src/main/resources/config.xml b/src/main/resources/config.xml index edd0225..795107b 100644 --- a/src/main/resources/config.xml +++ b/src/main/resources/config.xml @@ -14,23 +14,12 @@ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"> - - - - - - - + - - - + - - - - - - + + +