Java-第十五部分-源码解读-IOC重要的类、BeanDefinition注册流程和Bean实例化及属性赋值

194 阅读7分钟

源码解读全文

IOC

  • IOC,Inversion of Control,控制反转
  1. 将对象创建和调用过程交给Spring进行管理
  2. singletonObjects IOC容器的单例池
  • DI,Dependency Injection,依赖注入
  • 底层技术
  1. xml解析
  2. 工厂模式
  3. 反射
  • 初始化三部曲
  1. 定位,定位配置文件和扫描相关注解
  2. 加载,将配置信息载入到内存
  3. 注册,根据载入的信息,将对象初始化到IOCimage.png
  • IOC容器,本质上是对象工厂,有两种实现方式
  1. BeanFactorySpring内部的使用接口,基本实现;加载配置文件的时候,不会创建对象,获取或使用时才会进行创建
  2. ApplicationContextBeanFactory的子接口,提供了更多功能,面向开发人员;加载配置文件中,就会被创建

对象与对象之间的关系

  • 通过xml/properties/yml/文件进行表示
  • 存在classpath/network/filesystem/servletContext
  • 通过BeanDefinition统一配置文件的标准
  • 通过策略模式进行对不同的配置文件进行解析,最终输出成BeanDefinition

重要的接口和类

Resource

  • 资源类,包含一些文件读取的方式,通过NIO的方式进行
  1. web资源
  2. 远程服务器
  3. 本地磁盘 image.png

ResourceLoader

  • 资源加载器,进行加载资源,体现策略模式 image.png
  • 有多种实现策略 image.png
  • AbstractApplicationContext,为容器类,也就是环境类,包含着ResourcePatternResolver接口,并在初始化时,就为其赋值 image.png

BeanFactory

  • IOC容器最顶层接口,定义容器,为Spring整体的结构,返回Bean对象
  • 设计模式
  1. 抽象工厂
  2. 模板方法
  3. 组合模式,GenericApplicationContext组合了DefaultListableBeanFactory,可以获取所有的BeanFactory
  • HierarchicalBeanFactory,定义工厂的父子关系
  • ListableBeanFactory,可列举的BeanFactory,实现是DefaultListableBeanFactory
  • AutowireCapableBeanFactory,自动装配工厂 image.png

DefaultListableBeanFactory

  • BeanDefinition档案馆,同时是BeanFactory,也是BeanDefinitionRegistry,包锁了IOC所有的核心信息,且具有自动装配能力,实现了AutowireCapableBeanFactory
  • 只保存BeanDefinitionBean的定义信息,相当于图纸
  • List<String> beanDefinitionNames保存了所有beanDefinition名字
  • Map<Class<?>, String[]> singletonBeanNamesByType,类型为key,保存的beanName
  • Map<String, BeanDefinition> beanDefinitionMap保存所有beanDefinition

ApplicationContext

  • 事件派发器、国际化解析、bean工厂(自动装配被组合进)、资源解析器 image.png

Aware

  • 接口簇,需要使用spring中的组件,实现目标Aware接口

DefaultSingletonBeanRegistry

  • Spring默认的单例Bean注册中心
  • 其实现DefaultSingletonBeanRegistry,包含实际上的单例池singletonObjects

享元模式,将单例Bean保存在map中,相当于cache

BeanPostProcessor

  • Bean功能增强,在于改变,围绕着Bean的创建和初始化过程
  • 功能增强逻辑
  1. 注入了什么组件
  2. 在什么位置,用什么后置增强器,增强了什么

BeanFactoryPostProcessor

  • 后置增强工厂
  • 唯一的方法
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

InitializingBean

  • Bean初始化后,属性注入完之后,进行额外处理

线程池初始化之后,进行属性的显示

BeanDefinition注册流程

  • 断点在DefaultListableBeanFactoryregisterBeanDefinition
  • 获取所有Bean的定义信息,保存在BeanFactory
  • AppConfig.class配置类,是在BeanFactoryRegistryPostProcessor后置处理器ConfigurationClassPostProcessor中进行处理

XML流程

  • 在构建工厂时,进行BeanDefinition注册
  • 整体流程
  1. 获取xml资源路径
  2. resource包装为EncodedResource,再转换为Document
  3. BeanDefinitionParserDelegate进行解释
  4. DefaultListableBeanFactory加入到beanDefinitionMap,完成注册
  • new ClassPathXmlApplicationContext("classpath:beans.xml")
  • refresh();刷新容器
  • ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();第一次创建beanFactory,告诉子类刷新内部工厂
  • 创建DefaultListableBeanFactory,赋值id,并loadBeanDefinitions(beanFactory);
  • 准备读取器,将beanFactory分装成XmlBeanDefinitionReader加载beanDenifition,读取器中组合了IOC容器和资源读取器
  1. beanDefinitionReader.setEnvironment(this.getEnvironment());
  2. beanDefinitionReader.setResourceLoader(this);
  • 获取配置文件地址,并真正开始递归读取reader.loadBeanDefinitions(configLocations);,并记录个数;根据解析器策略不同,进行单个/多个解析资源 image.png
  • 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);放入 image.png
  • getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));注册完成后,发出一个通知事件

配置类流程

  • 注解配置,在工厂创建完成后,BeanDefinitionRegistryPostProcessor中的ConfigurationClassPostProcessor进行创建并注册
  • register(componentClasses);注册配置类
  • ConfigurationClassPostProcessor进行扫描处理,注册其他BeanDefinition

EncodedResource

  • 运用了适配器模式,对接RescourceInputStreamSource image.png

BeanDefinitionParserDelegate

  • 运用了解释器模式,包含了一个标签库,和解析方法,根据不同标签,进行不同的处理 image.png

创建BeanDefinition

  • 断点在AbstractBeanDefinition空构造方法
  • 获得doc文档后,解析出每一个节点,为其生成BeanDefinitionHolder

BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

  • parseBeanDefinitionElement进行标签解析
  • 最终调用BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());,封装成GenericBeanDefinition
  • 解析bean标签内的其他信息 image.png

Bean创建流程

  • Aware在完成bean实例化后进行,帮助装配底层组件
  1. 所有单实例对象,都要从容器中先获取,没有再创建
  • Aware功能由BeanPostProcessor完成

流程

  • 创建BeanFactory
  • 完成BeanFactory初始化,finishBeanFactoryInitialization(beanFactory);

AbstractApplicationContextrefresh方法中

  • 初始化非懒加载的单实例BeanbeanFactory.preInstantiateSingletons();
  1. !bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()非抽象,是单例bean,非懒加载
  2. 处理factoryBean,但是都会调用getBean image.png
  • Object sharedInstance = getSingleton(beanName);尝试从缓存中获取
  1. 三级缓存的应用 循环依赖梳理
  • 尝试获取父工厂BeanFactory parentBeanFactory = getParentBeanFactory();,从父工厂中尝试获取
  • 标记该Bean的创建状态,this.alreadyCreated.add(beanName);
if (!typeCheckOnly) {
   markBeanAsCreated(beanName);
}
  • 先处理dependOn,依赖的组件,先创建这些依赖的组件 image.png
  • getSingleton(beanName, mbd, args);创建实例,是由ObjectFactory(lambda表达式)进行调用,提供Bean实例

getSingleton方法中,会进行addSingleton(beanName, singletonObject);

sharedInstance = getSingleton(beanName, () -> {
   try {
      return createBean(beanName, mbd, args);
   }
   //..
});
  • 检查单例池,没有则锁住单例池double check
  1. beforeSingletonCreation(beanName);,加入singletonsCurrentlyInCreation
  2. singletonObject = singletonFactory.getObject();真正开始创建,实际上调用createBean(beanName, mbd, args);
  • Object bean = resolveBeforeInstantiation(beanName, mbdToUse);后置处理器的干预,可以让用户自定义Bean的创建,直接返回
  1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
  2. 如果返回了,那么直接调用BeanPostProcessor.postProcessAfterInitialization,进行后置处理
  • Object beanInstance = doCreateBean(beanName, mbdToUse, args);创建Bean实例。instanceWrapper = createBeanInstance(beanName, mbd, args);,创建完成后,包装成BeanWrapper(包括bn, bd),准备进行其他配置
  1. wrapper功能增强与包装;holder只包装
  2. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);,通过SmartInstantiationAwareBeanPostProcessor指定构造器
  3. ctors = mbd.getPreferredConstructors(); 使用自定义指定的构造器
  4. instantiateBean(beanName, mbd);,一般使用午参构造器,
  • 根据不同的创建策略进行实例化beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
  1. SimpleInstantiationStrategy利用反射,通过构造器创建
  2. CglibSubclassingInstantiationStrategy,利用cglib创建子类
  • applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);,修改bd信息
  1. MergedBeanDefinitionPostProcessor
  • 提前缓存刚刚创建好的Bean,还未进行赋值和其他初始化,解决循环依赖 image.png
  • populateBean(beanName, mbd, instanceWrapper);注入环节
  1. 通过后置处理器执行
  2. 允许提早中断
  • exposedObject = initializeBean(beanName, exposedObject, mbd);,对Bean进行初始化
  1. 处理基础的Aware接口invokeAwareMethods(beanName, bean);
  2. 初始化前,通过后置处理器处理,包括ApplicationContextAwareProcessor进行,配置Spring中的属性,invokeAwareInterfaces(bean);,如果实现了Aware接口就会进行处理
  3. 初始化,实现InitializingBean接口
  4. 初始化后,通过后置处理器处理

属性赋值

  • 发生在populateBean

xml方式

  • 属性值获取
  1. Bean类型,从BeanFactory获取Bean
  2. 普通属性,通过解析value属性获得,并保存在BD
  • PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);BeanDefinition拿到所有的属性键值对
  • 没有@Autowired注解,直接在applyPropertyValues(beanName, mbd, bw, pvs);进行属性赋值
  • 遍历赋值 image.png
  • writeMethod.invoke(getWrappedInstance(), value);通过反射获取set方法进行赋值

writeMethodsetter

Autowired

  • 基于注解,处理Autowired/Value/Inject注解
  • populateBean(beanName, mbd, instanceWrapper);赋值时执行postProcessAfterInstantiation
  • 通过遍历getBeanPostProcessorCache()后置处理器缓存器缓存,利用AutowiredAnnotationBeanPostProcessor进行处理
  • PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);进行属性赋值,位置与xml不同 image.png
  • InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);通过反射获取所有方法和属性,获取注解了Autowired
  • element.inject(target, beanName, pvs);遍历InjectedElement,通过反射进行setter
  1. @Autowired在属性上,直接赋值,Filed
  2. @Autowried在方法上,调用其方法,并加入pvs中,后续调用applyPropertyValues进行属性赋值,Method
  • 获取当前属性的val,调用result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
  1. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);,通过String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);获取所有匹配上的BeanName候选集合,是待注入类的实现或子类
  2. addCandidateEntry(result, candidate, descriptor, requiredType); 将类型加入候选集合result
  3. 如果查找到多个,进行名称匹配,如果对不上,则抛出异常
  4. 找到待注入的BeanType后,instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);通过getBean生成Bean
  • applyPropertyValues(beanName, mbd, bw, pvs);@Autowired添加到方法上的属性,进行真正赋值
  • bw.setPropertyValues(mpvs);BeanWrapper进行赋值