Spring XML IOC总结
2021-06-28 17:27:45 0 举报
spring ioc
作者其他创作
大纲/内容
抛出异常
ChildBeanDefinition
属性
BeanDefinition
调用BeanPostProcessor的前置处理方法postProcessBeforeInitialization()
返回对应的bean
FactoryBean一般情况下,Spring 通过反射机制利用 bean 的 class 属性指定实现类来实例化 bean。而 FactoryBean 是一种特殊的 bean,它是个工厂 bean,可以自己创建 bean 实例,如果一个类实现了 FactoryBean 接口,则该类可以自己定义创建实例对象的方法,只需要实现它的 getObject() 方法。注:很多中间件都利用 FactoryBean 来进行扩展。
registerListeners();
类型
是
一个RootBeanDefinition定义表明它是一个可合并的beandefinition:即在springbeanFactory运行期间,可以返回一个特定的bean。RootBeanDefinition用来在配置阶段进行注册beandefinition。但是,从spring 2.5后,编写注册beandefinition有了更好的的方法:GenericBeanDefinition。GenericBeanDefinition支持动态定义父类依赖,而非硬编码作为rootbeandefinition。
FactoryBean为了区分 “FactoryBean” 和 “FactoryBean 创建的 bean 实例”,Spring 使用了 “&” 前缀。假设我们的 beanName 为 apple,则 getBean(\"apple\") 获得的是 AppleFactoryBean 通过 getObject() 方法创建的 bean 实例;而 getBean(\"&apple\") 获得的是 AppleFactoryBean 本身。
onRefresh();
Bean 生命周期
initApplicationEventMulticaster();
注册监听器
InitDestroyAnnotationBeanPostProcessor中调用@PreDestroy注解方法
不存在
lazy-init
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri)通过该方法拿到对应的自定义标签的handler(定义在Resource/META-INF/spring.handlers中), 并调用handler 的init()方法加载不同的解析类(Parser)例如AOP 的处理类 : AopNamespaceHandler
mbd.getDependsOn();getBean(dep)
存在依赖项
几个重要的缓存,如下:mergedBeanDefinitions 缓存:beanName -> 合并的 bean 定义。beanDefinitionMap 缓存:beanName -> BeanDefinition。singletonObjects 缓存:beanName -> 单例 bean 对象。earlySingletonObjects 缓存:beanName -> 单例 bean 对象,该缓存存放的是早期单例 bean 对象,可以理解成还未进行属性填充、初始化。singletonFactories 缓存:beanName -> ObjectFactory。singletonsCurrentlyInCreation 缓存:当前正在创建单例 bean 对象的 beanName 集合。
校验是否存在循环依赖
自定义监听器实现如果我们想在 Spring IoC 容器构建完毕之后进行一些逻辑,就可以通过监听器来实现。创建一个自定义监听器,实现 ApplicationListener 接口,监听 ContextRefreshedEvent(上下文刷新完毕事件),并且将该监听器注册到 Spring IoC 容器即可。当 Spring 执行到 finishRefresh 方法时,就会将 ContextRefreshedEvent 事件推送到 MyRefreshedListener 中。跟 ContextRefreshedEvent 相似的还有:ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent,有兴趣的可以自己看看这几个事件的使用场景。当然,我们也可以自定义监听事件,只需要继承 ApplicationContextEvent 抽象类即可
尝试从缓存中获取 beanName 对应的实例
name
BeanNameAware进行setBeanName操作
Ioc容器初始化大致过程:1、通过ResourceLoader完成资源文件的定位;DefaultResourceLoader是默认实现,同时上下文对象本身也是ResourceLoader的实现;资源地位的方式可以为类路径、文件系统、URL等2、如果是解析XML文件的方式启动,解析Xml文件时,Xml文件被抽象成Resource对象;3、容器通过BeanDefinitionReader来完成Resource对象 的解析和Bean信息的注册,往往使用的时XmlBeanDefinitionReader作为实现类。4、XmlBeanDefinition实际处理过程委托给BeanDefinitionParserDelegate完成,从而得到bean的定义信息,并封装为BeanDefinition。5、容器解析得到Beandefinition之后,通过实现BeanDefinitionRegistry接口完成BeanDefinition 向IoC中注册的过程。注册过程实际时将BeanDefinition对象保存到IoC容器中的一个HashMap中,之后对Bean的操作都围绕这个HashMap展开。
判断scope是否合法
invokeBeanFactoryPostProcessors(beanFactory);
ConstructorArgumentValues
存在
拿到当前bean依赖的bean名称集合,在实例化自己之前,需要先实例化自己依赖的bean
初始化事件管理类
parent
getBean()实例化依赖项
本方法会注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中。BeanPostProcessor 接口是 Spring 初始化 bean 时对外暴露的扩展点,Spring IoC 容器允许 BeanPostProcessor 在容器初始化 bean 的前后,添加自己的逻辑处理。在 registerBeanPostProcessors 方法只将 BeanPostProcessor 实现类注册到 BeanFactory 的 beanPostProcessors 缓存中,具体调用是在 bean 初始化的时候。具体的:在所有 bean 实例化时,执行初始化方法前会调用所有 BeanPostProcessor 的 postProcessBeforeInitialization 方法,在执行初始化方法后会调用所有 BeanPostProcessor 的 postProcessAfterInitialization 方法。
obtainFreshBeanFactory()
该方法会实例化所有剩余的非懒加载单例 bean。除了一些内部的 bean、实现了 BeanFactoryPostProcessor 接口的 bean、实现了 BeanPostProcessor 接口的 bean,其他的非懒加载单例 bean 都会在这个方法中被实例化,并且 BeanPostProcessor 的触发也是在这个方法中。
prepareBeanFactory(beanFactory);
另外 在解析<context:component-scan> 节点时,主要做的事情有:1、扫描 base-package 目录,将使用了 @Component、@Controller、@Repository、@Service 注解的 bean 注册到注册表中(其实就是beanDefinitionMap、beanDefinitionNames、aliasMap缓存中),跟之前解析默认命名空间一样,也是在后续创建 bean 时需要使用这些缓存。2、添加了几个内部的注解相关的后置处理器:ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor 等。
否
执行完 obtainFreshBeanFactory 方法,我们得到了三个重要的对象:新的 BeanFactory。beanDefinitionNames 缓存。beanDefinitionMap 缓存。
autowire
BeanClassLoaderAware进行setBeanClassLoader操作
GenericBeanDefinition创建实例
创建bean createBean
调用BeanPostProcessor的postProcessBeforeDestruction
调用Aware
InitialzingBean的实现,调用afterPropertiesSet方法
调用InitMethods
init-method
判断是否为单例Singleton
同步锁 加入到alreadyCreated容器中标记为已创建
理解
dependency-check
doGetBean()
后置操作
methodOverrides
执行了创建 bean 实例前的一些准备操作
广播事件,初始化完成
GenericBeanDefinition
通过无参构造函数获取或工厂方法实例化bean
abstract
详细流程
getSingleton(beanName)
创建
实例化前的处理,给 InstantiationAwareBeanPostProcessor 一个机会返回代理对象来替代真正的 bean 实例,从而跳过 Spring 默认的实例化过程,
调用destroy-method
bean 创建流程
如果是scope 是Prototype的,校验是否有出现循环依赖
合法
RootBeanDefinition
@Autowire实现
检查这个bean 是否已经在缓存中存在
Bean实例化过程
对 bean 进行处理主要用于FactoryBean的特殊处理,普通Bean会直接返回sharedInstance本身
postProcessBeanFactory(beanFactory);
doGetBean(beanName);
doGetBean()流程
对BeanPostProcessor接口理解BeanPostProcessor接口类型实例是针对某种特定功能的埋点,在这个点会根据接口类型来过滤掉不关注这个点的其他类,只有真正关注的类才会在这个点进行相应的功能实现。比如:1、获取有@Autowired注解的构造函数埋点;过滤的接口类型是:SmartInstantiationAwareBeanPostProcessor调用的方法是:determineCandidateConstructors2、收集@Resource@Autowired@Value@PostConstruct,@PreDestroy注解的方法和属性的埋点过滤的接口类型是:MergedBeanDefinitionPostProcessor调用的方法是:postProcessMergedBeanDefinition3、循环依赖解决中bean的提前暴露埋点过滤的接口类型是:SmartInstantiationAwareBeanPostProcessor调用的方法是:getEarlyBeanReference4、阻止依赖注入埋点过滤的接口类型是:InstantiationAwareBeanPostProcessor调用的方法是:postProcessAfterInstantiation5、IOC/DI依赖注入埋点过滤的接口类型是:InstantiationAwareBeanPostProcessor调用的方法是:postProcessProperties
入参 beanFactoryPostProcessors:指AbstractApplicationContext对象中beanFactoryPostProcessors容器内的对象;通过实现类SpringApplicationContextInitializer并添加初始化参数 contextInitializerClasses 配置到 web.xml 中实现
invokeDisposableBean()
不存在依赖项或依赖项已经实例化
本方法会实例化和调用所有 BeanFactoryPostProcessor(包括其子类 BeanDefinitionRegistryPostProcessor)。1、BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。2、BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。 注:这边的 “常规 BeanFactoryPostProcessor” 主要用来跟 BeanDefinitionRegistryPostProcessor 区分。
primary
getBean(beanName);
调用BeanPostProcessor的后置处理方法postProcessAfterInitialization()
BeanFactoryAware进行setBeanFactory操作
如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
父 BeanFactory在 Spring 中可能存在多个 BeanFactory,多个 BeanFactory 可能存在 “父工厂” 与 “子工厂” 的关系。最常见的例子就是:Spring MVC 的 BeanFactory 和 Spring 的 BeanFactory,通常情况下,Spring 的 BeanFactory 是 “父工厂”,Spring MVC 的 BeanFactory 是 “子工厂”,在 Spring 中,子工厂可以使用父工厂的 BeanDefinition,因而,如果在当前 BeanFactory 中找不到,而又存在父工厂,则会去父工厂中查找
Aop 入口方法
创建bean createBean()
第一优先级:入参 beanFactoryPostProcessors 中的 BeanDefinitionRegistryPostProcessor, 调用 postProcessBeanDefinitionRegistry 方法(2.1.1)。第二优先级:BeanDefinitionRegistryPostProcessor 接口实现类,并且实现了 PriorityOrdered 接口,调用 postProcessBeanDefinitionRegistry 方法(3.8)。第三优先级:BeanDefinitionRegistryPostProcessor 接口实现类,并且实现了 Ordered 接口,调用 postProcessBeanDefinitionRegistry 方法(4.2)。第四优先级:除去第二优先级和第三优先级,剩余的 BeanDefinitionRegistryPostProcessor 接口实现类,调用 postProcessBeanDefinitionRegistry 方法(5.4)。第五优先级:所有 BeanDefinitionRegistryPostProcessor 接口实现类,调用 postProcessBeanFactory 方法(6)。第六优先级:入参 beanFactoryPostProcessors 中的常规 BeanFactoryPostProcessor,调用 postProcessBeanFactory 方法(7)。第七优先级:常规 BeanFactoryPostProcessor 接口实现类,并且实现了 PriorityOrdered 接口,调用 postProcessBeanFactory 方法(9.2)。第八优先级:常规 BeanFactoryPostProcessor 接口实现类,并且实现了 Ordered 接口,调用 postProcessBeanFactory 方法(10.3)。第九优先级:除去第七优先级和第八优先级,剩余的常规 BeanFactoryPostProcessor 接口的实现类,调用 postProcessBeanFactory 方法(11.2)。https://blog.csdn.net/v123411739/article/details/87741251
destroy-method
beanFactory.preInstantiateSingletons();
id
refresh()
校验父容器中是否存在相应的bean
finishRefresh();
autowire-candidate
finishBeanFactoryInitialization(beanFactory);
销毁
该方法会解析所有 Spring 配置文件(通常我们会放在 resources 目录下),将所有 Spring 配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中。常见的,如果解析到<context:component-scan base-package=\"\" /> 注解时,会扫描 base-package 指定的目录,将该目录下使用指定注解(@Controller、@Service、@Component、@Repository)的 bean 定义也同样封装成 BeanDefinition,加载到 BeanFactory 中。上面提到的 “加载到 BeanFactory 中” 的内容主要指的是添加到以下3个缓存: 1、beanDefinitionNames缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 集合。 2、beanDefinitionMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和 BeanDefinition 映射。 3、aliasMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和别名映射。
工作流程为:1、创建一个新的 BeanFactory:DefaultListableBeanFactory。2、根据 web.xml 中 contextConfigLocation 配置的路径,读取 Spring 配置文件,并封装成 Resource。3、根据 Resource 加载 XML 配置文件,并解析成 Document 对象 。4、拿到 Document 中的根节点,遍历根节点和所有子节点。5、根据命名空间,进行不同的解析,将 bean 节点内容解析成 BeanDefinition。6、将 BeanDefinition 注册到注册表中(也就是beanDefinitionMap、beanDefinitionNames、aliasMap缓存)。
ChildBeanDefinition是一种beandefinition,它可以继承它父类的设置,即ChildBeanDefinition对RootBeanDefinition有一定的依赖关系。 ChildBeanDefinition从父类继承构造参数值,属性值并可以重写父类的方法,同时 也可以增加新的属性或者方法。(类同于java类的继承关系)。若指定初始化方法,销毁方法或者静态工厂方法,ChildBeanDefinition将重写相应父类的设置。dependson,autowiremode,dependencycheck,sigleton,lazyinit一般由子类自行设定。
@Autowire 1、处理类:AutowiredAnnotationBeanPostProcessor 2、添加处理类的方法:AnnotationConfigUtils#registerAnnotationConfigProcessors3、添加处理类的时间点:refresh() -> obtainFreshBeanFactory() ->parseCustomElement() 解析<context:component-scan>标签 ->ComponentScanBeanDefinitionParser.parse()4、处理时间点1 (确定要用于给定 bean 的候选构造函数): doCreateBean -> createBeanInstance -> determineConstructorsFromBeanPostProcessors()5、处理时间点2(对使用了 @Autowire 注解的方法和属性进行预解析,并放到 injectionMetadataCache 缓存中,用于后续使用):doCreateBean -> applyMergedBeanDefinitionPostProcessors->postProcessMergedBeanDefinition();6、处理时间点3(对使用了 @Autowire 注解的方法和属性进行自动注入,将依赖的 bean 赋值给对应的属性)doCreateBean -> populateBean -> postProcessProperties()
解析自定义标签时delegate.parseCustomElement(ele)
MutablePropertyValues
前置操作
如果这个Bean配置了destroy-method属性,会自动调用其配置的销毁方法。
ConfigurationClassPostProcessor类@Cer等注解,对大家理解springboot帮助很大,真正的可以做到0xml配置。onfiguration@ComponentScan@Import@ImportResource@PropertySource@Ord
设置bean 属性
使用
registerBeanPostProcessors(beanFactory);
查找bean的依赖项
class
普通bean执行器init-method的方法
factory-method
判断是否为prototype
MergedBeanDefinitionMergedBeanDefinition:这个词其实不是一个官方词,但是很接近,该词主要是用来表示 “合并的 bean 定义”,因为每次都写 “合并的 bean 定义” 有点太绕口,因此我在之后的注释或解析中或统一使用 MergedBeanDefinition 来表示 “合并的 bean 定义”。之所以称之为 “合并的”,是因为存在 “子定义” 和 “父定义” 的情况。对于一个 bean 定义来说,可能存在以下几种情况:该 BeanDefinition 存在 “父定义”:首先使用 “父定义” 的参数构建一个 RootBeanDefinition,然后再使用该 BeanDefinition 的参数来进行覆盖。该 BeanDefinition 不存在 “父定义”,并且该 BeanDefinition 的类型是 RootBeanDefinition:直接返回该 RootBeanDefinition 的一个克隆。该 BeanDefinition 不存在 “父定义”,但是该 BeanDefinition 的类型不是 RootBeanDefinition:使用该 BeanDefinition 的参数构建一个 RootBeanDefinition。之所以区分出2和3,是因为通常 BeanDefinition 在之前加载到 BeanFactory 中的时候,通常是被封装成 GenericBeanDefinition 或 ScannedGenericBeanDefinition,但是从这边之后 bean 的后续流程处理都是针对 RootBeanDefinition,因此在这边会统一将 BeanDefinition 转换成 RootBeanDefinition。在我们日常使用的过程中,通常会是上面的第3种情况。如果我们使用 XML 配置来注册 bean,则该 bean 定义会被封装成:GenericBeanDefinition;如果我们使用注解的方式来注册 bean,也就是<context:component-scan /> + @Compoment,则该 bean 定义会被封装成 ScannedGenericBeanDefinition。
钩子方法
给beanFactory设置一些属性值
transformedBeanName(name)获取BeanName
initMessageSource();
depends-on
初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
真正创建 bean 实例的方法
收藏
0 条评论
下一页