Spring IOC(6) Spring Bean的创建 中
到目前为止,我们知道Spring创建Bean对象有5中方法,分别是:
使用FactoryBean的getObject方法创建
使用BeanPostProcessor的子接口InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法创建
设置BeanDefinition的Supplier属性进行创建
设置BeanDefinition的factory-method进行创建
使用全过程:getBean-->doGetBean-->createBean-->doCreateBean 反射进行创建
现在讲述使用全过程创建一个Bean
解析构造函数继续看AbstractAutowireCapableBeanFactory的createBeanInstance方法中的源码:
123456789// Candidate constructors for autowiring?// 明确构造器 在BeanPostProcessor,对应的是 AutowiredAnnotationBeanPostProce ...
Spring IOC(7) Spring Bean的创建 下
在上节中,将述了Spring Bean的实例化,循环依赖在Spring中是如何解决的,这一节 继续完成Bean的创建流程。
对象的属性填充属性填充,可能会涉及到很多东西,比如填充的属性是基本类型还是引用类型,填充的方式又可以分为按类型、按名称还是其他的,然后填充时值的类型是否需要进行类型转换等。
1populateBean(beanName, mbd, instanceWrapper);
属性填充大致可以分为对基本类型的数据进行填充和对应用类型的数据填充,populateBean方法中代码比较繁琐,会设计到很多的递归调用,最终解析并填充属性。
使用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation接口的调用,可以在属性填充前对Bean进行修改,并且可以定制字段的填充,postProcessAfterInstantiation入参有Bean对象和Bean的名称,可以在这里面进行自定义的属性注入,如果返回false表示后续不需要spring帮我们进行依赖注入,反之需要spring帮我们进行依赖注入
按 ...
Spring IOC(5) Spring Bean的创建 上
到目前为止,Spring源码中AbstractApplicationContext#refresh方法的已经解读到第11个方法finishBeanFactoryInitialization,前10个方法介绍了:
BeanFactory的准备,创建,刷新,个性化BeanFactory的扩展点,自定义属性解析;
环境信息Environment的加载(包括环境变量、系统变量等);
BeanDefinition的加载,解析;
BeanFactoryPostProcessor的注册与执行流程,BeanDefinitionRegistryPostProcessor的解析,ConfigurationClassPostProcessor对Spring注解的解析过程(@Component、@PropertySources、@PropertySource、@ComponentScans、@ComponentScan、@Import等注解的解析)
BeanPostProcessor的注册流程;
国际化,Spring事件驱动的加载执行过程;
在前面,通过注解或XML的方式解析生成了BeanDefiniti ...
Spring IOC(4) 国际化和事件发布
在 Spring IOC(3) 我们介绍了Spring IOC中的prepareRefresh、obtainFreshBeanFactory、prepareBeanFactory。
本章介绍AbstractApplicationContext#refresh的第7, 8, 10个方法,国际化和事件发布。第9个方法onRefresh刷新蓉器这个方法是一个空方法,由子类实现,这里直接跳过了。
国际化单纯的Spring中设置国际化实际上是体现不出来的,需要用到Spring MVC 才能有所体现。
初始化国际化123456789101112131415161718192021222324252627282930313233protected void initMessageSource() { // 获取beanFactory ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 如果工厂中已经有这个bean,那就获取出来设置到messageSource上 if (beanFactory. ...
Spring IOC(3) BeanFactoryPostProcessor和registerBeanPostProcessors
在 Spring IOC(2) 我们介绍了Spring IOC中的prepareRefresh、obtainFreshBeanFactory、prepareBeanFactory。
本章介绍AbstractApplicationContext#refresh的第4、5、6个方法
postProcessBeanFactory(beanFactory)
invokeBeanFactoryPostProcessors
registerBeanPostProcessors
postProcessBeanFactoryAbstractApplicationContext中的postProcessBeanFactory方法为空方法。
postProcessBeanFactory这个方法跟BeanFactoryPostProcessor接口中的方法一样,但是它的功能是提供给子类进行添加一些额外的功能,比如添加BeanPostProcessor接口的实现,或者定制一些其他的功能,因为这个方法你可以拿到BeanFactory,自然是可以对它进行一些功能的定制的。
12345@Function ...
Spring IOC(2) 容器的的创建的工作
在IOC(1)中介绍了Spring Bean的生命周期,并引出了AbstractApplicationContext#refresh方法,本节将介绍refresh方法中的
prepareRefresh:创建容器前的工作。
obtainFreshBeanFactory: 创建BeanFactory。
prepareBeanFactory: 准备BeanFactory。
prepareRefresh 方法Spring的前戏准备大概就是做了以下几件事:
设置容器的启动时间
设置容器的停止状态为false
设置容器的激活状态为true
获取环境信息并验证必要的属性
准备监听器和事件的容器
12345678910111213141516171819202122232425262728293031323334353637protected void prepareRefresh() { // Switch to active. // 设置启动时间 设置标识位 this.startupDate = System.currentTimeMillis(); // 设置容 ...
Spring IOC(1) Bean创建的整体流程
Spring IOC 中涉及的重要接口
BeanDefinitionBean的描述信息,实现类包括 RootBeanDefinition 和 GenericBeanDefinition,Bean的描述信息中定义了一系列Bean的信息,比如:beanClassName、scope、lazyinit、dependsOn、primary、initMethodName、destroyMethodName、isSington、isAbstract等信息。
BeanDefinitionReader
用于解析Bean的资源阅读器,比如针对于XML文件的配置的Bean,实现类XmlBeanDefinitionReader,针对properties文件的配置的Bean,实现类为PropertiesBeanDefinitionReader,Spring在启动时会将xml文件通过loadBeanDefinitions方法进行解析。
BeanFactory是IOC容器实现的顶层接口,默认的实现为DefaultListableBeanFactory,Spring Bean 的整个生命周期都是由Default ...
单调栈
概念单调递增栈:
在一个队列中针对每一个元素从它右边寻找第一个比它小的元素
在一个队列中针对每一个元素从它左边寻找第一个比它小的元素
单调递减栈:
在一个队列中针对每一个元素从它右边寻找第一个比它大的元素
在一个队列中针对每一个元素从它左边寻找第一个比它大的元素
单调栈何时用:为任意一个元素找左边和右边第一个比自己大/小的位置用单调栈.
单调递增栈用于找到当前元素左边第一个小于它的的元素
例如:54361207,这个数组获得左边和右边第一个比自己大的位置.使用让数组依次进入单调栈,0位置的5进栈,1位置的4进栈,2位置的3进栈,当4位置的6进栈时,为了保证栈的单调性,需要依次将2->3、1->4、0->5出栈,只要一个数据开始弹出,它的信息就开始生成,左边第一个比自己大的数就是栈中被自己压的数,右边第一个比自己大的数就是让自己弹出的数。对于2->3来说,左边是0->4,右边是4->6。
数组遍历完之后,如果栈中还存在数据,就依次弹出数据,只有左边第一个比自己大的数,就是栈中被自己压的数。因为每个数据只进栈和出栈一次,所有时间复杂度为O ...
滑动窗口
题目leetcode 239 有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置。
12345678例如,数组为[4,3,5,4,3,3,6,7],窗口大小为3时:[4 3 5] 4 3 3 6 74 [3 5 4] 3 3 6 74 3 [5 4 3] 3 6 74 3 5 [4 3 3] 6 74 3 5 4 [3 3 6] 74 3 5 4 3 [3 6 7]窗口中最大值为5,窗口中最大值为5 ,窗口中最大值为5,窗口中最大值为4,窗口中最大值为6,窗口中最大值为7
如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值。
请实现一个函数。输入:整型数组arr,窗口大小为w。输出:一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的以本题为例,结果应该为[5,5,5,4,6,7]
滑动窗口滑动窗口就是一个动态的窗口,这个窗口可以是固定长度,也可以是可变长度。使用双端队列实现滑动窗口这种数据结构,滑动窗口从头部到尾部由大到小。
双端队列维持的是什么信息?如果目前的R不在扩大,让L依次移动1个位置,得到每个位置时窗 ...
Manacher算法
解决的问题字符串中最长回文子串的长度如何求解?
如何做到时间复杂度O(n)完成?
例如:abc1 232 0del 最长回文子串为232。
经典解法将每个字符从中间开始向两边扩展可以得到最长回文子串吗?不能。
因为只能得到奇数的回文子串。 例如:1221。
上面只处理了实轴,我们加入虚轴。将字符串中每个字符中间加入特殊符号,如#,得到扩充字符,再使用上面的解法就可以得到答案。
例如:
将1221扩充为: #1#2#2#1,从每个字符向两边扩展,得到每个字符的最长回文串,最中间#的为9,除2,得到最长回文子串为4。
但是,加入的字符必须是没有出现的字符吗?不需要,每次处理字符串都是实轴和实轴比,虚轴和虚轴比,1和1比,#和#比。
经典解法的时间复杂度O(n)
Manacher解法概念回文直径和回文半径,回文直径是一个位置向2边扩的长度叫回文直径,一半是回文半径。
回文串的最右边界:,只要突破边界,就记录突破的位置。#1#2#2#1 对于第1个字符1来说是0-2,就是2;对于对于第3个字符2来说是2-4就更新为4;对于第4个字符#是0-8。
取得更远边界时中心点:对于第1个字符1来说是0- ...