规范命名,有助于思想的传承。
最近在阅读Spring的过程当中,发现除了 AOP,IOC以外,还有许多被忽略的有助于阅读/理解源码的点,在此一一作笔记,供人参阅,但愿有所帮助。若有错漏,但愿可以指出以便修正,不胜感激。web
Spring 的源码中,核心类的命名与功能划分具备必定的规范,了解后,在阅读Spring源码中,有些许的帮助。spa
Spring底层核心类,不少接口是按照幂等与非幂等/读写分离进行划分的:
BeanFactory:内部方法均为获取或者判断的方法,如:getBean
,containsBean
等;
ConfigurableBeanFactory:继承了BeanFactory
后,内部定义了属性设置的入口,非幂等的,如:setParentBeanFactory
,setConversionService
Environment:内部方法均为获取,或者判断的方法,如:containsProperty
,getActiveProfiles
;
ConfigurableEnvironment:继承了Environment
后,内部方法定义的是设置方法,非幂等的,如:setActiveProfiles
,merge
;code
Spring 的 接口定义中,接口的命名有其规范性存在, 单纯的幂等性方法,直接按实际做用命名(主要为幂等性), 非幂等性,则在实际做用命名前(继承了幂等性类),增长 `Configurable`, 基础实现,则在非幂等性的基础上(继承了非幂等性类),对方法进行通用的基础实现
Environment:拥有获取 property
,profile
的方法
ConfigurableEnvironment:拥有setActiveProfiles
等方法
AbstractEnvironment:对以上两个类方法进行基础实现orm
ApplicationContext:拥有获取 ID
,BeanFactory
等方法,如:getApplicationName
,getParent
,getAutowireCapableBeanFactory
ConfigurableApplicationContext:拥有设置对应属性的方法,如:setEnvironment
,setParent
AbstractApplicationContext:对上述两个类方法进行基础实现xml
PropertyResolver:获取属性的方法,如:getProperty
,containsProperty
ConfigurablePropertyResolver:设置性的方法,如:setConversionService
,setPlaceholderPrefix
AbstractPropertyResolver:对以上两个类方法继续基础实现继承
PropertyAccessor:属性的判断及获取
ConfigurablePropertyAccessor:属性的设置
AbstractPropertyAccessor:基本实现递归
针对向某个 Collection 中添加/注册某个实例,Spring 经常使用的命名方式是使用 Registry 做为后缀,就实际功能而言,这些类是将对应实例归入Spring容器管理的入口!
ConverterRegistry:转换器注册器,提供了 addConverter
,addConverterFactory
等方法
AliasRegistry:别名注册器,registerAlias
,removeAlias
,isAlias
,getAliases
BeanDefinitionRegistry:Bean定义注册器,提供了registerBeanDefinition
,removeBeanDefinition
SingletonBeanRegistry:单例注册器,方法:registerSingleton
,containsSingleton
接口
默认实现,在Abstract***以后,使用了Default前缀
如:DefaultConversionService
,DefaultListableBeanFactory
,DefaultNamespaceHandlerResolver
资源
当一个类有层级概念(代表该类在处理时须要考虑父级状况)时,会定义一个前缀:`HierarchicalXxx` 的类,这个类内部的方法会涉及到:`setParent`,`getParent`,如:
HierarchicalBeanFactory:有内部方法,getParent
,containsLocalBean
HierarchicalMessageSource:有内部方法,setParentMessageSource
,getParentMessageSource
rem
对于加载的命名,使用的是 `XxxLoader`,如:
ContextLoader:上下文加载(web
应用的时候)
ResourceLoader:资源加载的时候
DocumentLoader:加载 XML
文档
仅总结上述,掌握了Spring的命名规范后(实际只在核心功能类——基础context/beanfactory 中常见,后续其余类命名未见强制以上规范),在阅读源码过程当中,就不会由于各类命名致使思绪混乱,好比:
看到ConfigurableXxx
的类,就知道它是主管设置的入口,看到getParent
,就知道对应的类应该是继承了HierarchicalXxx
;
如:在AbstractBeanFactory
方法:getMergedBeanDefinition
中,有以下一段代码,在进行分析的过程当中,依据命名规范,咱们能够比较清晰地理解获取过程
try { parentBeanName = transformedBeanName(bd.getParentName()); if (!beanName.equals(parentBeanName)) { // 递归获取合并后的父定义,出口是:getParentName == null (即上述 if) pbd = getMergedBeanDefinition(parentBeanName); } else { // 这里处理的状况是,子 beanName 与 父 beanName 相同! // 在通常状况下,若是咱们在同一个 xml 文件中,定义了两个相同的 beanName,是会抛异常的, // 但这里却有处理 beanName 相同的状况 // 此时就须要回顾,BeanFactory 有子类 HierarchicalBeanFactory,这种工厂具备层级关系, // 而 BeanName 能够相同,且 beanName 分属父子,在同一层级的 BeanFactory,即便父子关系,同名也会异常 // 因此,这里就须要上溯父级工厂,去父级工厂就行递归 parentName 的 Bean定义(只有在父级工厂,才容许由相同名称的 beanName) // 而父级工厂为何要判断是 ConfigurableBeanFactory 呢? // 由于 beanName 的设置入口,由 ConfigurableBeanFactory 提供,若是不是此种类型,那在 Spring 体系中,是不容许的(不规范的) BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); // 从父工厂开始继续递归 Bean定义 } else { throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without a ConfigurableBeanFactory parent"); } } }
再,咱们平时的使用中,经常会执行(BeanFactory)ApplicationContext
来强转并使用BeanFactory
的方法getBean
获取单例,就规范而言,是由于BeanFactory
是做为获取的入口。
常见的继承关系有:DefaultXxx
--> 继承 AbstractXxx
--> 继承 ConfigurableXxx
--> Xxx
这样,最终子类将拥有设置与获取的方法。了解一些命名约束,有助于更好地理解源码本义,以上均为我的阅后感,若有错误,还请指正。