Spring源码分析之IOC的三种常见用法及源码实现(二)

  • 时间:
  • 浏览:1
  • 来源:UU快3—全天最准大发快三

也就越来越你的@Bean注解里面越来越写name的事先,实际上默认可是我拿措施名做beanName了!

前面是对配置类的一个判断处理,里面可是我doProcessConfigurationClass真正处理了,处理完事先加入到configurationClasses中,也可是我最后搞笑的话。亲戚亲戚当当我们查看源码:

并且 往后看

一点个list进行不断筛选分类 并且 进行invokeBeanDefinitionRegistryPostProcessors措施调用

继续查看:

原来们就先来看看findCandidateComponents措施源码是为甚把什么BeanDefinition搞出来的:

还可不可否看出,一点BeanDefinitionHolder实际上可是我个BeanDefinition的一个小包装。

亲戚亲戚当当我们铺垫了前置知识越来越就对其中的

亲戚亲戚当当我们大致来看看,前三句是把配置类背熟来、拿措施数据、措施名。里面一个判断是要看看要未必跳过,跳过就直接return了,不注册。再往后是把@Bean注解里的name对应的值背熟来,也可是我别名背熟来并注册,里面也是各种把@Bean注解里的东西取出来操作,autowire模型(通过id还是name?)、initMethod、destroyMethod,各种细节配置就很多说了。最后通过this.registry.registerBeanDefinition就注册进去了

for循环遍历basePackages,再通过findCandidateComponents措施拿到每个basePageage下的类BeanDefinition们,里面可是我给每个BeanDefinition进行配置。

这里貌似也没干啥,可是我把配置类里面的打了bean注解的措施返回背熟来了,啥也没干。越来越一点@Bean注解标注里的创建对象到底在哪里创建并加到容器呢?

综上核心可是我一点invokeBeanDefinitionRegistryPostProcessors的逻辑,亲戚亲戚当当我们来看看:

非常好懂,就一个if else,首先获取beanfactory,翻看源码知道一点beanfactory可是我上篇文章讲的初始化父类时创建的DefaultListableBeanFactory,拿到这玩意。还是围绕这玩意的功能操作

parser.parse(candidates);里面是校验和创建配置类的Set。注意到另一个措施:

ok,一探到底了,开始英语 英语 回到上层调用吧。

接下来判断beanfactory里是全是有一点APPLICATION_EVENT_MULTICASTER_BEAN_NAME,翻看源码:

亲戚亲戚当当我们只看亲戚亲戚当当我们事先查看源代码的parse措施那付进 和里面就行了,有个do while循环解析那:

遍历集合,并调用对应措施,继续查看源码:

ok讲完了,回到代码。

打开里面的multicastEvent措施

讲一点事先铺垫一点前置基础知识

仔细看下就发现重点了,其实 最终可是我调用listener.onApplicationEvent(event);,而一点onApplicationEvent可是我ApplicationListener接口唯一的措施。换句话说,你只要实现一点接口类,并加入@Compent加入容器中,就会调用你实现类的onApplicationEvent里你此人 的代码!

这里又是分了一种生活清况 去解析,第一种生活从名字还可不可否看出来注解的那种解析,第二种是AbstractBeanDefinition这是对XML配置措施的解析,很明显亲戚亲戚当当我们看第一种生活,继续查看源码:

一个解析类型、一个执行invokeListener,进去再看看一点咋invokeListener调用的

进行的不断深挖,那就往下看吧:

通过措施注释更加取舍 了,最后一句代码正是容器注册代码。

这里明显可是我个预操作,越来越真正的操作在上层调用里面(实际上一点parse解析措施里也就越来越@ComponentScan的真正处理了),亲戚亲戚当当我们返回上层直到有parse措施的地方:来到ConfigurationClassPostProcessor的processConfigBeanDefinitions措施:

全读出来事先,返回上层doScan措施的这里:

这里的第一句

一点措施里还有别的注解的解析。比如亲戚亲戚当当我们一点系列最开始英语 英语 给的例子:通过Java配置类配置bean 可是我用的@Bean注解。原来们来看看@Bean注解。

进行讲解

现在还可不可否看得人重点了,有一行注释:

看看,给了注释,辅助类 :用于事件挂接的。

第一个for循环是把所有listener都加到Multicaster里了(它用来通知相关事件)。其中

至此,@Bean注解也分析完毕.

一点注释提示得非常明显,继续跟进loadBeanDefinitionsForConfigurationClass:

这里面一点addBeanMethod措施打开一看:

spring中是通过ApplicationListener及ApplicationEventMulticaster来进行事件驱动开发的,即实现观察者设计模式或发布-订阅模式。

又是一堆代码...总体看下来会发现,前面95%全是给下面这句话设置参数:

啰嗦了很长一大段,其实 是一点校验、对同名BeanDefinition的处理啥的,核心就一句:

是把亲戚亲戚当当我们的配置类也可是我sourceClass,获取了元数据传到一点注解工具类里去了,是把配置类里面的@ComponentScan注解解析为对象了,原来方便里面拿到注解里设置的值。

这里来到了核心重点,要解析亲戚亲戚当当我们的配置类了!弄了个do while循环保证一点一点list里的东西都解析完,亲戚亲戚当当我们来看看解析措施parser.parse(candidates);吧!它是为甚解析的:

值得注意的是beanName来自里面的:

这里大段全是try catch了,并且 涉及到一点一点失败的清况 ,都做了处理。

OK,原来们就把@ComponentScan相关源码分析完了。

一点是从容器中拿ApplicationListener.class类型的,从名字也还可不可否看出来getBeanForType,背熟来事先也插进Multicaster里(它用来通知相关事件),这也可是我为甚亲戚亲戚当当我们还可不可否此人 实现ApplicationListener接口并且 打上@Component注解事先能通知的意味着 了!它在这里加带了。

里面主要还做了filter的判断,判断是就越来越你是全是exclude了一点 原来就不读了,并且 读出来是全是打了Component注解的,最后条件都满足搞笑的话就把读出来的信息就加到 最终的一个LinkedHashSet的集合里去了,进行返回。

这里是检查ComponentScan扫出来的类是全是又打了ComonentScan注解,并且 就时要递归解析了。

这里的措施就比较好懂了,并且 一点此人 平时都写过。第一个明显拼字符串,拼最终要读取的资源文件路径,并且 把文件路径交给resourcePatternResolver,获取一个Resource类(继承自InputStreamSource),一点可是我个IO流读取。

最后registerBeanDefinition注册到容器里去。说实话我又好奇是咋注册的,不断打开源码:

BeanDefinitionRegistryPostProcessor:继承一点类它的实现措施还可不可否在spring的bean未加载定义事先加些亲戚亲戚当当我们此人 定义的bean定义

ApplicationEventMulticaster:用来通知所有的观察者对象,属于观察者设计模式中的Subject对象。

并且 细心的同协会发现事先前面看得人的registerListeners中最后一段里获取的是earlyApplicationEvents,一点early是什么意思?实际上是把Multicaster还没创建时就并且 缓存的事件给获取播放,并且 事先来了事件可是我能丢掉啊。越来越什么过完会有一点early事件呢?实际上是在refresh()代码里的registerListeners措施的前一句onRefresh措施中,一点措施默认是越来越early事件的,会在springboot中使用.

仔细读里的逻辑会发现前半段是围绕:

至此ioc构造器的三大措施中的refresh(),里的invokeBeanFactoryPostProcessors的每段就讲完了,剩下的下篇文章继续分析。

ApplicationListener:监听容器中发布的事件,只要事件地处,就触发监听器的回调,来完成事件驱动开发。属于观察者设计模式中的Observer对象。

很明显继续跟进一点invokeBeanFactoryPostProcessors同名措施:

到了这里有种终见神龙真身的感觉。。。终于开始英语 英语 对亲戚亲戚当当我们常用的什么注解分别进行解析了。。亲戚亲戚当当我们还可不可否挑哪几个最常用的看看,来看看非常常用的@ComponentScan注解吧!

可是我继续解析了,查看源码:

亲戚亲戚当当我们看Spring源码会发现,Spring源码里真正干活的全是doXXX措施,会发现这里终于也发现一个了,

可是我个ConcurrentHashMap,在DefaultListableBeanFactory类里的一个private私有成员变量,一点一点也可见DefaultListableBeanFactory类的重要性,BeanDefinition都地处它这了,容器。

查看一点beanDefinitionMap

BeanFactoryPostProcessor:继承一点的类它的实现措施还可不可否在spring的bean定义好事先 而未实例化的事先做一点逻辑操作

注意到里面有个重点啊:

这里可是我最后真正扫描了,查看源码:

这两句话的实现,其中来到了主角儿AnnotationConfigApplicationContext的构造器实现:

而后半段是围绕:

这也太明显了哈,把配置的bean措施背熟来,一个个去加载,继续跟进:

IOC三大常用springbean配置用法,还有个是通过@ComponentScan配置的,SpringBoot也是通过一点。

源码如下:

至此registerListeners措施也讲完了。

给扫描出来的BeanDefinition设置scope,单例多例、搞一个名字给一点BeanDefinition,以及判断是注解形式配置的还是XML形式配置的给它设置一点默认的配置,比如默认的懒加载设置各种,spring有默认的并且 读你设置的。最后把一点BeanDefinition和名字一起包装成BeanDefinitionHolder,通过:

而beanMehtods是个private final Set beanMethods = new LinkedHashSet();

接下来亲戚亲戚当当我们来讲讲refresh()中的invokeBeanFactoryPostProcessors(beanFactory);

设置注册id、并且 这里显然主要逻辑在processConfigBeanDefinitions,继续查看:

是全是可是我事先铺垫知识的listener?用来通知事件的。看看它在什么都越来越容器里面,什么都越来越搞笑的话走else创建一个,并且 作为单例注册进去,在搞笑的话就从容器里面取出来赋值给当前this对象即亲戚亲戚当当我们的主角儿AnnotationConfigApplicationContext,而主角一种生活没定义一点是在主角父类AbstractApplicationContext里定义的,亲戚亲戚当当我们看看:

回到事先的ConfigurationClassParser类的doProcessConfigurationClass措施中,是一点措施里开始英语 英语 的各种注解的解析:

回顾上文 亲戚亲戚当当我们研究的是

综上所述,一点initApplicationEventMulticaster()这行代码可是我获取事件通知发布类的,越来越搞笑的话就以单例创建一个插进容器并拿给主角儿,并且 就直接拿到给主角儿。接下来看原来registerListeners();

比较长,分几每段看,第一每段开始英语 英语 英语 是创建一个ArrayList,类型是BeanDefinitionHolder,亲戚亲戚当当我们看看一点:

获取亲戚亲戚当我们全是注解里写的basePackages,进行环境路径设置,最后加到事先创建的hashset类型的basePackages变量里去。并且 设置排除filter到扫描器。最后一句又到了核心代码了。

很明显ClassPathBeanDefinitionScanner是真正用来扫描类的,类注释写了“A bean definition scanner that detects bean candidates on the classpath”,里面全是给扫描器设置各种名字生成器、scope、resourcePattern、以及include和exclude和是否懒加载,直到下面这段事先才开始英语 英语 注意路径:

继续看,里面的代码可是我从registry容器中拿bean名字出来并且 又根据名字把BeanDefinition背熟来,最后把名字和BeanDefinition一种生活一起装入list里面去了,再排个序。里面又创建了两bean名字生成器。

一个list进行分类加带进去,并且 进行invokeBeanDefinitionRegistryPostProcessors措施调用

其中this()和register(annotatedClasses);看得人了,亲戚亲戚当当我们这次来看看refresh();

感觉是啥也没干,可是我加带了而已。越来越看看retrieveBeanMethodMetadata是在干嘛了,打开:

最后一段是获取早期事件,获取了事先for循环进行触发事件。亲戚亲戚当当我们来看看它到底是个为甚触发的。

亲戚亲戚当当我们事先是对这里的:

一点操作reader的loadBeanDefinitions比较贴近意思了,点进去看看: