java spring 加载bean,Spring多种加载Bean方式解析
1 定义bean的方式
常见的定义Bean的方式有:
通过xml的方式,例如:
?
通过注解的方式,在Class上使用@Component等注解,例如
?
通过在@Configuration类下的@Bean的方式,例如
?
虽然这三种定义Bean的方式不一样,对应的处理细节也不一样,但是从大的逻辑上来看,都是一样。主要的流程如下图: 最关键的就是问题就是这么去找到定义Bean的方式,然后生成BeanDefinition后注册到Spring上下文中,由Spring自动创建Bean的实例。
2 BeanDefinition
BeanDefinition是一个接口,用来描述一个Bean实例,例如是SINGLETON还是PROTOTYPE,属性的值是什么,构造函数的参数是什么等。简单来说,通过一个BeanDefinition我们就可以完成一个Bean实例化。 BeanDefinition及其主要的子类:
下面简单说一下各个子类:
RootBeanDefinition和ChildBeanDefinition: 这2个BeanDefinition是相对的关系,自Spring 2.5 出来以后,已经被GenericBeanDefinition代替。因为这样强迫我们在编写代码的时候就必须知道他们之间的关系。
GenericBeanDefinition: 相比于RootBeanDefinition和ChildBeanDefinition在定义的时候就必须硬编码,GenericBeanDefinition的优点可以动态的为GenericBeanDefinition设置parent。
AnnotatedBeanDefinition:看名字就是知道是用来读取通过注解定义Bean。
3 通过xml文件定义Bean
通过xml定义Bean是最早的Spring定义Bean的方式。因此,怎么把xml标签解析为BeanDefinition(), 入口是在org.springframework.beans.factory.xml.XmlBeanDefinitionReader这个类,但是实际干活的是在org.springframework.beans.factory.xml.BeanDefinitionParserDelegate。代码很多,但实际逻辑很简单,就是解析Spring定义的 等标签 。
4 通过@Component等Spring支持的注解加载Bean
如果要使用@Component等注解定义Bean,一个前提条件是:有或者@ComponentScan注解。但这2个方式还是有一点点区别:
4.1
由于是一个xml标签,因此是在解析xml,生成的类org.springframework.context.annotation.ComponentScanBeanDefinitionParser,关键代码:
?
4.2 @ComponentScan
注解对应生成的类是org.springframework.context.annotation.ComponentScanAnnotationParser 其实最后实际干活的还是ClassPathBeanDefinitionScanner这个。ComponentScanAnnotationParser类的生成是伴随着@Configuration这个注解处理过程中(意思说@ComponentScan必须和@Configuration一起使用)。而处理@Configuration其实是org.springframework.context.annotation.ConfigurationClassPostProcessor。是不是感觉有点绕。
其实简单来说,在处理@Configuration的时候发现有@ComponentScan注解,就会生成ComponentScanAnnotationParser去扫描@Component注解
4.3 ClassPathBeanDefinitionScanner
上面说到了,无论注解还是标签的方式,最后都会交给ClassPathBeanDefinitionScanner这个类来处理,这个类做的就是1.扫描basePackage下所有class,如果有@Component等注解,读取@Component相关属性,生成ScannedGenericBeanDefinition,注册到Spring中。
5 通过@Bean方式
前面说了@ComponentScan是在@Configuration处理过程中的一环,既然@Bean注解也是必须和@Configuration一起使用,那么说明@Bean的处理也是在@Configuration中,其实最后是交给ConfigurationClassBeanDefinitionReader这个类来处理的,关键代码:
?
6 把BeanDefinition实例化
前面分别说了怎么把不同定义Bean的方式转换为BeanDefinition加入到Spring中去(确切来说是保持在BeanFactory的BeanDefinitionMap中),实例是在ApplicationContext最后阶段,关键代码在DefaultListableBeanFactory中
?
通过getBean最后最后实例的代码,在AbstractAutowireCapableBeanFactory中
?
从上面初始化可以看出,InitializeBean和BeanPostProcessors的调用顺序
7 总结
综上分析,Spring加载Bean其实大的思想都是一样的,先读取相关信息生成BeanDefinition,然后通过BeanDefinition初始化Bean。如果知道了上面了套路以后,就可以清楚怎么自定义Xml标签或者自定义注解向Spring中注入Bean。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/lizo/p/6759080.html
java spring 加载bean,Spring多种加载Bean方式解析相关推荐
- SpringBoot原理篇:bean的多种加载方法之 使用上下文对象regist注入bean
使用上下文对象regist注入bean package com.qing.app;import com.qing.bean.Cat; import com.qing.bean.Dog; import ...
- Spring Boot 学习系列(09)—自定义Bean的顺序加载
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Bean 的顺序加载 有些场景中,我们希望编写的Bean能够按照指定的顺序进行加载.比如,有UserServ ...
- spring bean的懒加载原理
spring bean的懒加载原理 1 普通的bean的 初始化是在初始化阶段开始执行的,而被lazy-init修饰的bean则是从容器第一次进行context.getbean("" ...
- spring的applicationContext.xml如何自动加载
一个web工程自动加载的配置文件只有web.xml,想要加载其他.xml必须在web.xml里面进行配置. 用spring的时候需要一个bean容器来管理所有的bean,所有bean默认是写在appl ...
- spring boot实战(第六篇)加载application资源文件源码分析
前言 在上一篇中了解了spring配置资源的加载过程,本篇在此基础上学习spring boot如何默认加载application.xml等文件信息的. ConfigFileApplicationLis ...
- webmvcconfigurer配置跨域_为什么加了 Spring Security 会导致 Spring Boot 跨域失效呢?...
点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达 作者:欧阳我去 链接:https://segmentfault.com/a/1190000019485883 作为一个后端开发,我们经常遇到 ...
- Spring源码之BeanDifinition(加几行代码,可以产出让队友几天也找不出的Bug)
前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger 种一棵树最好的时间是十年前,其次是现在 我知道很多人不玩qq ...
- SpringXML方式配置bean的懒加载lazy-init
lazy-init(懒加载),表示该bean在容器初始化的时候不进行初始化. 例如: <bean name="role1" class="com.fz.entity ...
- 使用 加载 顺序_SpringBoot系列教程之Bean加载顺序之错误使用姿势辟谣
在网上查询 Bean 的加载顺序时,看到了大量的文章中使用@Order注解的方式来控制 bean 的加载顺序,不知道写这些的博文的同学自己有没有实际的验证过,本文希望通过指出这些错误的使用姿势,让观文 ...
- java中class文件如何加载的_jvm如何加载class文件
编译期: javac是JDK自带的编译器, 可以将java文件编译为class字节码文件, javap是JDK自带的反编译器,将.class字节码反编译为.java文件,javap -help是jav ...
最新文章
- react 开发过程中的总结/归纳
- 【长篇连载】桌面管理演义 第八回 电脑中毒很危险 告警隔离防传染
- Java一行一行的读文件和简单的写文件
- 【运筹学】表上作业法 ( 求初始基可行解 | 最小元素法 )
- MySQL not exists 真的不走索引么?
- UBoot常用命令手册
- mac系统更新后code .命令打不开vs code
- 慕课网高并发实战(一)-并发与高并发基本概念
- leetcode 1052. 爱生气的书店老板(滑动窗口)
- opencv-api FlannBasedMatcher
- OC无法进行多人会话
- Appcan、apicloud、HBuilder 不同之处解析
- CentOS - 安装mysql
- dom4j解析xml_JAVADom、Sax解析XML详解
- 计算机在线拥有,电路在线计算器
- ABB机器人FOR循环指令
- npm-Babel转码器
- LINUX gdk/X11正确获取DPI/Resolution的函数
- 《城市化》(顾朝林)-1
- Compose 页面切换动画
热门文章
- X64-CL iPro 采集卡OC-64EO-IPRO0简介
- js tostring 16 java_js中toString()和String()区别详解
- mysql database table_mysqldump database table
- Entity Framework 小知识(一)
- ORA-00704 ORA-00604 ORA-00942----惜分飞
- Python_Day10_进程、线程、协程
- ubuntu 下 github 使用方法 以及异常修改
- Frequently Asked Questions — Scrapy 0.15.1 documentation
- win7系统计算机无最小化,win7纯净版系统任务栏无法显示网页最小化窗口怎么办...
- 开了立体声混音仍然不能内录_蓝牙音箱有个功能很鸡肋,用好了秒变HIFI立体声...