源码解读全文
IOC
- IOC,Inversion of Control,控制反转
- 将对象创建和调用过程交给
Spring进行管理singletonObjectsIOC容器的单例池
- DI,Dependency Injection,依赖注入
- 底层技术
- xml解析
- 工厂模式
- 反射
- 初始化三部曲
- 定位,定位配置文件和扫描相关注解
- 加载,将配置信息载入到内存
- 注册,根据载入的信息,将对象初始化到
IOC中
- IOC容器,本质上是对象工厂,有两种实现方式
BeanFactory,Spring内部的使用接口,基本实现;加载配置文件的时候,不会创建对象,获取或使用时才会进行创建ApplicationContext,BeanFactory的子接口,提供了更多功能,面向开发人员;加载配置文件中,就会被创建
对象与对象之间的关系
- 通过
xml/properties/yml/文件进行表示 - 存在
classpath/network/filesystem/servletContext - 通过
BeanDefinition统一配置文件的标准 - 通过
策略模式进行对不同的配置文件进行解析,最终输出成BeanDefinition
重要的接口和类
Resource
- 资源类,包含一些文件读取的方式,通过
NIO的方式进行
- web资源
- 远程服务器
- 本地磁盘
ResourceLoader
- 资源加载器,进行加载资源,体现
策略模式 - 有多种实现策略
AbstractApplicationContext,为容器类,也就是环境类,包含着ResourcePatternResolver接口,并在初始化时,就为其赋值
BeanFactory
- IOC容器最顶层接口,定义容器,为
Spring整体的结构,返回Bean对象 - 设计模式
- 抽象工厂
- 模板方法
- 组合模式,
GenericApplicationContext组合了DefaultListableBeanFactory,可以获取所有的BeanFactory
HierarchicalBeanFactory,定义工厂的父子关系ListableBeanFactory,可列举的BeanFactory,实现是DefaultListableBeanFactoryAutowireCapableBeanFactory,自动装配工厂
DefaultListableBeanFactory
BeanDefinition档案馆,同时是BeanFactory,也是BeanDefinitionRegistry,包锁了IOC所有的核心信息,且具有自动装配能力,实现了AutowireCapableBeanFactory- 只保存
BeanDefinition,Bean的定义信息,相当于图纸 List<String> beanDefinitionNames保存了所有beanDefinition名字Map<Class<?>, String[]> singletonBeanNamesByType,类型为key,保存的beanName池Map<String, BeanDefinition> beanDefinitionMap保存所有beanDefinition
ApplicationContext
- 事件派发器、国际化解析、
bean工厂(自动装配被组合进)、资源解析器
Aware
- 接口簇,需要使用
spring中的组件,实现目标Aware接口
DefaultSingletonBeanRegistry
Spring默认的单例Bean注册中心- 其实现
DefaultSingletonBeanRegistry,包含实际上的单例池singletonObjects
享元模式,将单例
Bean保存在map中,相当于cache
BeanPostProcessor
Bean功能增强,在于改变,围绕着Bean的创建和初始化过程- 功能增强逻辑
- 注入了什么组件
- 在什么位置,用什么后置增强器,增强了什么
BeanFactoryPostProcessor
- 后置增强工厂
- 唯一的方法
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
InitializingBean
Bean初始化后,属性注入完之后,进行额外处理
线程池初始化之后,进行属性的显示
BeanDefinition注册流程
- 断点在
DefaultListableBeanFactory的registerBeanDefinition - 获取所有
Bean的定义信息,保存在BeanFactory中 AppConfig.class配置类,是在BeanFactoryRegistryPostProcessor后置处理器ConfigurationClassPostProcessor中进行处理
XML流程
- 在构建工厂时,进行
BeanDefinition注册 - 整体流程
- 获取
xml资源路径- 将
resource包装为EncodedResource,再转换为Document- 由
BeanDefinitionParserDelegate进行解释DefaultListableBeanFactory加入到beanDefinitionMap,完成注册
new ClassPathXmlApplicationContext("classpath:beans.xml")refresh();刷新容器ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();第一次创建beanFactory,告诉子类刷新内部工厂- 创建
DefaultListableBeanFactory,赋值id,并loadBeanDefinitions(beanFactory); - 准备读取器,将
beanFactory分装成XmlBeanDefinitionReader加载beanDenifition,读取器中组合了IOC容器和资源读取器
beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);
- 获取配置文件地址,并真正开始
递归读取reader.loadBeanDefinitions(configLocations);,并记录个数;根据解析器策略不同,进行单个/多个解析资源 XmlBeanDefinitionReader中进行registerBeanDefinitions(doc, resource),dom解析,xml变成document文档,reader实际上是负责解析doc的,交由BeanDefinitionDocumentReader进行真正解析
Document doc = doLoadDocument(inputSource, resource);
- 由
DefaultBeanDefinitionDocumentReader调用parseBeanDefinitions(root, this.delegate);,解析doc,并由BeanDefinitionParserDelegate进行逐个节点解析
BeanDefinitionParserDelegate代理对象,是一个标签库和解析器
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());解析完标签后,封装成BeanDefinitionHolder,使用工具类,进行注册,并会处理别名- 检查是否存在,不存在
this.beanDefinitionMap.put(beanName, beanDefinition);放入 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));注册完成后,发出一个通知事件
配置类流程
- 注解配置,在工厂创建完成后,
BeanDefinitionRegistryPostProcessor中的ConfigurationClassPostProcessor进行创建并注册 register(componentClasses);注册配置类ConfigurationClassPostProcessor进行扫描处理,注册其他BeanDefinition
EncodedResource
- 运用了适配器模式,对接
Rescource和InputStreamSource
BeanDefinitionParserDelegate
- 运用了解释器模式,包含了一个标签库,和解析方法,根据不同标签,进行不同的处理
创建BeanDefinition
- 断点在
AbstractBeanDefinition空构造方法 - 获得
doc文档后,解析出每一个节点,为其生成BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
parseBeanDefinitionElement进行标签解析- 最终调用
BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());,封装成GenericBeanDefinition - 解析
bean标签内的其他信息
Bean创建流程
Aware在完成bean实例化后进行,帮助装配底层组件
- 所有单实例对象,都要从容器中先获取,没有再创建
Aware功能由BeanPostProcessor完成
流程
- 创建
BeanFactory - 完成
BeanFactory初始化,finishBeanFactoryInitialization(beanFactory);
AbstractApplicationContext的refresh方法中
- 初始化非懒加载的单实例
Bean,beanFactory.preInstantiateSingletons();
!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()非抽象,是单例bean,非懒加载- 处理
factoryBean,但是都会调用getBean
Object sharedInstance = getSingleton(beanName);尝试从缓存中获取
- 三级缓存的应用 循环依赖梳理
- 尝试获取父工厂
BeanFactory parentBeanFactory = getParentBeanFactory();,从父工厂中尝试获取 - 标记该
Bean的创建状态,this.alreadyCreated.add(beanName);
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
- 先处理
dependOn,依赖的组件,先创建这些依赖的组件 getSingleton(beanName, mbd, args);创建实例,是由ObjectFactory(lambda表达式)进行调用,提供Bean实例
该
getSingleton方法中,会进行addSingleton(beanName, singletonObject);
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
//..
});
- 检查单例池,没有则锁住单例池
double check
beforeSingletonCreation(beanName);,加入singletonsCurrentlyInCreationsingletonObject = singletonFactory.getObject();真正开始创建,实际上调用createBean(beanName, mbd, args);
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);后置处理器的干预,可以让用户自定义Bean的创建,直接返回
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation- 如果返回了,那么直接调用
BeanPostProcessor.postProcessAfterInitialization,进行后置处理
Object beanInstance = doCreateBean(beanName, mbdToUse, args);创建Bean实例。instanceWrapper = createBeanInstance(beanName, mbd, args);,创建完成后,包装成BeanWrapper(包括bn, bd),准备进行其他配置
wrapper功能增强与包装;holder只包装Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);,通过SmartInstantiationAwareBeanPostProcessor指定构造器ctors = mbd.getPreferredConstructors();使用自定义指定的构造器instantiateBean(beanName, mbd);,一般使用午参构造器,
- 根据不同的创建策略进行实例化
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
SimpleInstantiationStrategy利用反射,通过构造器创建CglibSubclassingInstantiationStrategy,利用cglib创建子类
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);,修改bd信息
MergedBeanDefinitionPostProcessor
- 提前缓存刚刚创建好的
Bean,还未进行赋值和其他初始化,解决循环依赖 populateBean(beanName, mbd, instanceWrapper);注入环节
- 通过后置处理器执行
- 允许提早中断
exposedObject = initializeBean(beanName, exposedObject, mbd);,对Bean进行初始化
- 处理基础的
Aware接口invokeAwareMethods(beanName, bean);- 初始化前,通过后置处理器处理,包括
ApplicationContextAwareProcessor进行,配置Spring中的属性,invokeAwareInterfaces(bean);,如果实现了Aware接口就会进行处理- 初始化,实现
InitializingBean接口- 初始化后,通过后置处理器处理
属性赋值
- 发生在
populateBean中
xml方式
- 属性值获取
Bean类型,从BeanFactory获取Bean- 普通属性,通过解析
value属性获得,并保存在BD中
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);从BeanDefinition拿到所有的属性键值对- 没有
@Autowired注解,直接在applyPropertyValues(beanName, mbd, bw, pvs);进行属性赋值 - 遍历赋值
writeMethod.invoke(getWrappedInstance(), value);通过反射获取set方法进行赋值
writeMethod为setter
Autowired
- 基于注解,处理
Autowired/Value/Inject注解 populateBean(beanName, mbd, instanceWrapper);赋值时执行postProcessAfterInstantiation- 通过遍历
getBeanPostProcessorCache()后置处理器缓存器缓存,利用AutowiredAnnotationBeanPostProcessor进行处理 PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);进行属性赋值,位置与xml不同InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);通过反射获取所有方法和属性,获取注解了Autowired的element.inject(target, beanName, pvs);遍历InjectedElement,通过反射进行setter
@Autowired在属性上,直接赋值,Filed@Autowried在方法上,调用其方法,并加入pvs中,后续调用applyPropertyValues进行属性赋值,Method
- 获取当前属性的
val,调用result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);,通过String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);获取所有匹配上的BeanName候选集合,是待注入类的实现或子类addCandidateEntry(result, candidate, descriptor, requiredType);将类型加入候选集合result- 如果查找到多个,进行名称匹配,如果对不上,则抛出异常
- 找到待注入的
BeanType后,instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);通过getBean生成Bean
applyPropertyValues(beanName, mbd, bw, pvs);对@Autowired添加到方法上的属性,进行真正赋值bw.setPropertyValues(mpvs);,BeanWrapper进行赋值