spring-core模块笔记,主要从包模块拆开看的,类太多了,有些比较常用的类直接列出功能方便使用
annotation支持
@AliasFor别名注解,用于进行注解的属性值起别名与注解的属性覆盖等,spring本身大量使用,最直观的感觉是注解属性好像能继承一样
AnnotatedElementUtils:支持注解属性的覆盖(这个工具类产生的结果是全面支持@AliasFor的功能的,它支持了属性覆盖,借助AnnotationUtils.synthesizeAnnotation支持了别名)
getXXX(在当前类和注解层次上进行搜索),findXXX(除getXXX支持外还在接口/继承体系上进行搜索,所以推荐使用这个,比如findMergedAnnotation)
AnnotationUtils:基本注解工具,也有getXXX和findXXX和AnnotatedElementUtils语义类似,只不过不支持属性覆盖(它和AnnotatedElementUtils唯一的区别就是不支持属性覆盖而已,其他都支持,比如别名,相当于支持了一部分@AliasFor的功能,就是没有支持annotation这个方法而已).
synthesizeAnnotation提供了一些合成注解的功能,(实际上@AliasFor别名的功能是在这里实现的,在访问注解属性时它通过动态代理进行判断这个方法有没有别名,进而取出别名的值进行返回,具体的可以看这个链接https://www.jianshu.com/p/869ed7037833)
convert类型转换
spring中所有类型进行转换的实现A—>B
转换逻辑相对简单,有Converter接口匹配原类与目标类匹配,其次还有条件匹配ConditionalConverter转换.
通过ConfigurableConversionService接口(实现类为DefaultConversionService)管理Converter与ConditionalConverter.同时统一对外提供服务注册,转换等功能.
典型的如springmvc的类型转换就是通过这套机制实现的.
Env环境&配置
PropertySource/MapPropertySource/PropertiesPropertySource 这是一个配置源的抽象
PropertySources/MutablePropertySources 这是一组配置源的抽象
PropertyResolver 这是配置解析定义,它被分化为两部分
Environment/AbstractEnvironment/StandardEnvironment 这是环境定义体系
ConfigurablePropertyResolver/AbstractPropertyResolver/PropertySourcesPropertyResolver 这是配置解析的体系
注意点就是环境和配置的概念是隔离的,他俩在实现上完全没有任何交集
实际上环境也只是配置文件中的一个参数,而这个参数比较特殊,key是指定的,我们称这个key所获得的value值为为环境
Serializer
这里看到的只是定义了serializer和deserializer接口,然后默认实现是使用的jdk的ObjectInputStream和ObjectOutputStream序列化实现的
Style
这个风格是指toString的风格,是自定义toString的一些信息,规范了spring内部的toString样式(搜索了一下适用范围,发现只有写测试用例的时候在用它打印一些参数与返回值信息...).它的核心实现是通过ToStringCreator这个工具类实现的,其他几个接口都是一些功能抽象与委托实现.
目前使用的较多的是apache的commons.long3包ToStringBuilder工具类,这个看起来更适合在类内部自己用
Task
TaskExecutor类似于Executor,实际上要早于它.它的实现有SyncTaskExecutor同步直接调用与AsyncTaskExecutor和AsyncListenableTaskExecutor作为异步接口的拓展最终由SimpleAsyncTaskExecutor提供实现,它内部即支持了限流器,也支持了ThreadFactory线程池,异步Feture通过FutureTask进行实现返回的.监听则是通过ListenableFutureTask继承自FutureTask然后重写了done方法进行回调success与failure监听.
IO资源抽象
Resource 资源的抽象(主要提供转换为InputStream的能力,比如常见的ClassPathResource)
ResourceLoader 对于资源加载能力的抽象(就是如何找到资源,主要提供查找对应的Resource)
Type
这部分还是很重要的,spring的加载元信息都在这里实现,分为三部分
1元信息
ClassMetadata-类元信息接口
MethodMetadata-方法元信息接口
AnnotationMetadata-带注解的类的元信息(方便获取类上的注解信息)接口
实际上这些元信息如果要加载再获取的话就没价值了,后面再MetadataReader的实现类SimpleMetadataReader中会通过AnnotationMetadataReadingVisitor访问者进行分析class字节码信息获取这些元信息,也就是不加载class但是分析class获取信息.
2元信息获取能力
主要是通过ResourceLoader(DefaultResourceLoader实例)获取Resource,并且通过分析Resource进而获取元信息实例
MetadataReader-持有Resource后进行分析字节码获取元信息
MetadataReaderFactory-一般情况全局对象,用于产生MetadataReader实例以及缓存
实际上可以将MetadataReader看成是元信息的上下文,它持有所有的ClassMetadata与AnnotationMetadata.也就是将Metadata又向上抽象了一层
3元信息匹配过滤器
TypeFilter-针对MetadataReader进行一些条件过滤,
常见的实例有AnnotationTypeFilter(通过匹配注解过滤),RegexPatternTypeFilter(通过全类名的正则匹配过滤)
实际用的地方非常多,因为加载之后需要过滤才是自己希望要的,一般情况都是注解过滤,也就是AnnotationTypeFilter这个类
结合ResourceLoader串起来看一下
分开看这三部分好像没什么关系,实际上列一下扫描实现的流程就能明白他们之间的关系了(扫描类代码看ClassPathBeanDefinitionScanner的scan方法跟踪)
这样一看就能看出来他们的关系了,从ResourceLoader加载Resource实例,然后通过MetadataReaderFactory换取MetadataReader,然后在BeanDefinition中提供分析,也就是为什么此时bean并没有被加载,反而就可以分析啦,实际上是分析的字节码信息获取的.
Core
AliasRegistry-别名注册表的顶层接口/SimpleAliasRegistry简单map实现类
AttributeAccessor-属性访问器的顶层接口-AttributeAccessorSupport简单的用Map存储实现
Constants-对static final方法的反射访问封装
Conventions-提供框架内部的各种命名.比如参数命名,返回值命名
DecoratingClassLoader/OverridingClassLoader-ClassLoader增加了排除与添加包路径功能的基础拓展
ParameterNameDiscoverer-参数名发现者,这个功能有时候还是能够用到的,其中比较常见的实现是LocalVariableTableParameterNameDiscoverer,通过解析字节码信息获取参数名
ExceptionDepthComparator-异常深度比较器.其中findClosestMatch静态方法直接使用即可比较一组异常中对目标异常最接近的异常,这是mvc全局异常进行选择对比的实现部分
MethodClassKey-method+object作为一个唯一的key,用于一般的指定对象与方法的调用结果缓存.并且实现了Comparable比较器
MethodIntrospector-提供一些Method的查询/过滤
MethodParameter-方法/构造函数与参数组成的一个Helper类
NamedThreadLocal/NamedInheritableThreadLocal-ThreadLocal和InheritableThreadLocal的可命名子类
OrderComparator-Spring内部的排序器.主要是PriorityOrdered最先升序,其次Ordered升序,其他都是最低.spring-web的拦截器顺序就是通过它排序的
AnnotationAwareOrderComparator-支持注解和接口混合的排序器,sort静态方法直接使用,内部使用较多
ResolvableType-对Field,Method,Class进行封装便于操作反射api
SerializableTypeWrapper-对于Field,MethodParameter,Class的序列化包装类
Util
简单设计/拓展-还有一些拓展在其他模块中,这里不列
backoff包-一个可重试的计数器,默认实现有乘数增长型ExponentialBackOff和固定增长型FixedBackOff
comparator包-很多比较器的实现包
concurrent包-模仿guava的ListenableFuture,实现类增强了FutureTask,提供Future的完成方法监听支持.在1.8中基本可以被CompletableFuture类替代了
IdGenerator-ID生成器实现的有JdkIdGenerator/AlternativeJdkIdGenerator/SimpleIdGenerator
PathMatcher-AntPathMatcher,Ant风格的路径匹配器,非常常用,简单的规则有"?一个字符,多个字符,*多级目录"
AutoPopulatingList-通过委托ArrayList实现了List,区别是get(index)的时候如果获取为null,那么会自动的通过反射新建对象填充并返回,好像没什么用
ConcurrencyThrottleSupport-简单的限流器支持,它的使用在SimpleAsyncTaskExecutor这个异步执行器执行时的限流选项
ConcurrentReferenceHashMap-使用soft/weak引用了key和value的ConcurrentHashMap
CustomizableThreadCreator-自定义一些线程信息.比如线程名,是否守护线程
PropertiesPersister-对Properties对象操作的一层委托封装
InstanceFilter-实例过滤器.在集合中匹配过滤对象,子类可以拓展实际匹配方法.比如ExceptionTypeFilter类,拓展的是异常类为子类就算是匹配了
MultiValueMap-一键多值的映射(Key-List<V>).实现的有LinkedMultiValueMap(委托ListedHashMap)
MethodInvoker-辅助性质的方法调用
MimeType/MimeTypeUtils-MimeType基本可以看做Content-Type.比如下面的图
PropertyPlaceholderHelper-占位符替换,用的非常多
StopWatch-简单的计时对象-一般用于开发测试中
StringValueResolver-String值解析器,常见的有PlaceholderResolvingStringValueResolver/EmbeddedValueResolver适配BeanExpressionResolver
纯工具类-杂项,框架内部使用居多
Assert-断言工具类
Base64Utils-可以使用jdk自带的Base64工具类
DigestUtils-摘要工具类.比如md5摘要,sha256摘要等操作或者使用guava的Hashing(推荐),这个流式api用起来更爽快
StreamUtils-io工具.简单的copy操作工具.
FileCopyUtils-file copy顺便close掉io
FileSystemUtils-文件夹的递归删除和创建
ClassUtils-对于一些反射方法的封装,提供了很多对基础类型,代理,桥接方法等特殊方法的支持
ObjectUtils-对Object的工具提供.很多基础类型数组的HashCode支持
CollectionUtils-集合工具支持
NumberUtils-一些Number检查/转换
PatternMatchUtils-简单匹配器-xxx* *xxx xxx pattern styles.
ReflectionUtils-Spring中的反射工具类,比较常用
主要提供属性/方法的遍历,属性获取/方法调用(转换为运行期异常),常用Object中方法的判断
(isToStringMethod,isHashCodeMethod,isEqualsMethod,isObjectMethod…)
常用:
doWithXXX(递归遍历属性或方法) doWithLocalXXX(遍历本类的方法或属性)
getAllDeclaredMethods:递归遍历获取所有声明方法
invokeMethod,getField:将声明异常转为运行异常避免try-catch
ResourceUtils-做一些资源类型判断,加载文件操作
SerializationUtils-jdk的serialize/deserialize方法
SocketUtils-查找可用的tcp/udp端口
StringUtils-简单的String功能,以及String数组的功能StringUtils.tokenizeToStringArray这个分割字符串的方法比较厉害,可以传入多个分隔符
SystemPropertyUtils-提供占位符的形式(${env.key:defaultValue})替换为System.getProperty的值
这么多基础工具类一部分是为了自定义错误信息输出,很多方法都是参数判空,然后反射方法调用,出错了可以自定义为框架错误输出
总结
1很多管理器职责在命名上都抽象出了新的概念从而从新命名了.打破了各种XXX-Manager这样的命名,也就是根据实际用途将这种管理器命名为xxx解析器,xxx注册器,xxx加载器,xxx工厂,将Manager的功能命名化,突出概念
2功能抽象的很细致.像Environment还专门会有一个ConfigurableEnvironment继承它来提供Environment的写入/修改能力
3包装类(装饰者模式)用的很多.比如说有一些后置操作,增强操作,那就包装一层.对原代码无侵入,内部实现也好看一些
4经常是双接口演化,分别演进到不同的接口,然后下层到实现类时采用继承/委托将此功能撇到别的类中实现