- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Spring启动过程源码分析及简介由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
本文是通过AnnotationConfigApplicationContext读取配置类来一步一步去了解Spring的启动过程.
在看源码之前,我们要知道某些类的作用,这样更方便后续的了解.
。
BeanDefinition就是Bean的定义,它是用来描述Bean的,里面存放着关于Bean的一系列信息,比如Bean的作用域,Bean所对应的Class,是否懒加载等等,BeanDfinition与Bean的关系可以看作是类和class的关系,那么有人说,有class对象就好啦,但是Class不能完完全全的抽象出Bean,比如说,Bean的注入模型,是否懒加载,是否是工厂bean等等,这些是class无法去抽象出来的,所以需要BeanDefinition来描述Bean,在Spring中,我们可以通过<Bean><Bean/>、@Component、BeanDefinition来定义Bean 。
//定义一个BeanDefinitionAbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();//设置当前bean的class 1、通过class获取 2、通过类的全限定类名获取//beanDefinition.setBeanClass(Testt.class);beanDefinition.setBeanClassName("com.beans.Testt");//将beanDefinition注册到BeanFactory中DefaultListableBeanFactory factory = new DefaultListableBeanFactory();factory.registerBeanDefinition("BEAN",beanDefinition);//获取Beanfactory.getBean("BEAN");
还可以直接使用RootBeanDefinition来获取BeanDefinition 。
//生成BeanDefinitionRootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Testt.class);DefaultListableBeanFactory factory = new DefaultListableBeanFactory();//将BeanDefinition注册到工厂中factory.registerBeanDefinition("tt",rootBeanDefinition);Object tt = factory.getBean("tt");System.out.println(tt);
通过上述三种方式我们就可以定义一个Bean.
假设我们有一个实体类Testt 。
public class Testt { public String name; public void sayHello(){ System.out.println("Hello World!"); } public void setName(String name){ this.name = name; } public String getName(){ return name; }}
我们还可以通过beanDefinition来给name属性赋值 。
//生成一个BeanDefinitionRootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Testt.class);//赋值属性name为123rootBeanDefinition.getPropertyValues().addPropertyValue("name","123");//获取name的值Object name = rootBeanDefinition.getPropertyValues().getPropertyValue("name").getValue();DefaultListableBeanFactory factory = new DefaultListableBeanFactory();factory.registerBeanDefinition("tt",rootBeanDefinition);Testt tt = (Testt) factory.getBean("tt");System.out.println(tt);//通过实例获取name的值String name1 = tt.getName();System.out.println(name1); //123System.out.println(name);//123
BeanDefinition还可以 。
beanDefinition.setScope("prototype"); // 设置作用域beanDefinition.setInitMethodName("init"); // 设置初始化方法beanDefinition.setAutowireMode(0); // 设置自动装配模型 0默认装配模式不自动注入,1 ByName 2 ByType 3 构造器注入 ......
BeanDefinition还有很多功能,在这里就不一一去说明了,感兴趣的读者可以通过查看beanDefinition的接口和实现类对其一一了解.
无论通过哪种方式来定义Bean,都会被解析为BeanDefinition对象,总之,Bean与BeanDefinition之间的关系你是可以看作是类和class的关系,这样就很容易去理解它了.
这里有一个mergedBeanDefinitions,我们来说一下它是做什么的,mergedBeanDefinitions是存储合并后的BeanDefinition的ConcurrentHashMap,Spring会对BeanDefinition进行合并,基于合并后的BeanDefinition去创建Bean 。
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
那么,什么时候beanDefinition会进行合并呢?我们举出下列的一个例子,来带大家一探究竟 。
首先写一个Spring.xml,我们通过xml文件去声明bean 。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="parent" scope="prototype"/> <bean id="children" parent="parent"/></beans>
这里,我们指将parent的scope设置为prototype,而children并没有去设置他的scope属性,默认就是单例的,我们通过下面方式去调试,看看mergedBeanDefinitions中到底存的是什么 。
public class mainT { public static void main(String[] args) { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("Spring.xml"); classPathXmlApplicationContext.getBean("children"); }}
我们通过在getBean上打上断点,进行调试后,我们可以看到FactoryBean中的mergedBeanDefinitions存的参数如下图所示 。
children的scope属性也成为了prototype,这就是合并后的BeanDefinition。其实就相当于子类继承父类的时候包含父类的属性 。
这里还要记录一下RootBeanDefinition和GenericBeanDefinition的显在区别 。
可以发现GenericBeanDefinition的SetParentName是正常的,可以添加 。
public void setParentName(@Nullable String parentName) { this.parentName = parentName; }
而RootBeanDefinition是会报错的,也会直接返回null 。
@Override public String getParentName() { return null; } @Override public void setParentName(@Nullable String parentName) { if (parentName != null) { throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference"); } }
。
从名字来看,这是一个工厂类,它负责生产和管理bean,在Spring中,BeanFactory是IOC容器的核心接口,他有很多职责和功能,它的核心实现类是DefaultListableBeanefauFactory类。下图是DefaultListableBeanefauFactory类的UML图.
DefaultListableBeanefauFactory实现了很多接口,也说明了DefaultListableBeanefauFactory类继承了很多功能 。
我们可以通过beanfactory做很多事,例如:
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();beanDefinition.setBeanClass(Testt.class);DefaultListableBeanFactory factory = new DefaultListableBeanFactory();//注册BeanDefinitionfactory.registerBeanDefinition("Testt",beanDefinition);//注册别名factory.registerAlias("Testt","T");//获取beanObject alias = factory.getBean("T");System.out.println(alias);//com.beans.Testt@6b1274d2//通过类型获取BeanString[] beanNamesForType = factory.getBeanNamesForType(Testt.class);System.out.println(beanNamesForType[0]);//Testt//获取BeanDefinitionBeanDefinition testt = factory.getBeanDefinition("Testt");System.out.println(testt);//Generic bean: class [com.beans.Testt]; scope=; abstract=false; lazyInit=null; autowireMode=0; //dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; //initMethodName=null; destroyMethodName=null//获取BeanDefinition个数int beanDefinitionCount = factory.getBeanDefinitionCount();System.out.println(beanDefinitionCount);//获取Bean的提供者ObjectProvider<Testt> beanProvider = factory.getBeanProvider(Testt.class); System.out.println(beanProvider);//org.springframework.beans.factory.support.DefaultListableBeanFactory$1@6a472554
等等.
ApplicationContext继承BeanFactory接口,它是Spring的一种更更高级的容器,提供了更多有用的功能,我们可以看到ApplicationContext的实现类GenericApplicationContext中有一个属性 。
private final DefaultListableBeanFactory beanFactory;
那么他既然已经继承了BeanFactory接口,为什么又要增加一个DefaultListableBeanFactory属性呢,可以从上面看到DefaultListableBeanFactory实现了很多接口,拥有很多功能,这么做的目的就是,使GenericApplicationContext通过DefaultListableBeanFactory间接拥有了DefaultListableBeanFactory继承的那些功能,而无需在去继承或者实现。o 。
这里要说明一下别名和beanName的存储,也是通过map去存储的,{aliasname:beanname},key为别名,value为bean的名字 。
。
可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解, 。
它能解析的注解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description 。
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();AnnotatedBeanDefinitionReader Reader = new AnnotatedBeanDefinitionReader(factory);/*** 也可以使用registerBean(Testt.class) 或者 registerBean(Testt.class,"指定Bean名字")**/Reader.register(Testt.class);Object testt = factory.getBean("testt");System.out.println(testt);
。
这个并不是BeanDefinitionReader,但是它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition 。
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new ClassPathBeanDefinitionScanner(factory);//得到该包下类的个数// int scan = classPathBeanDefinitionScanner.scan("com.beans");// System.out.println(scan);//6//扫描没有加@Componment注解的类,并注册到容器中,未通过注解或其他方式定义Bean的类也不会添加到容器中//classPathBeanDefinitionScanner.addExcludeFilter(new AnnotationTypeFilter(Component.class));//扫描加了@Componment注解的类,并注册到容器中classPathBeanDefinitionScanner.addIncludeFilter(new AnnotationTypeFilter(Component.class));//获取beanObject bean = factory.getBean(BeanTest.class);System.out.println(bean);//com.beans.BeanTest@5ccddd20
。
ConditionEvaluator是一个Spring中的内部类,他提供了@Condition注解的判定条件作用,具体可以看它的shouldSkip方法.
。
Aware翻译过来是感知的意思,他的用意是用来让用户感知到一些信息,比如说BeanNameAware 。
@Componentpublic class User implements BeanNameAware { private String awareName; @Override public void setBeanName(String name) { this.awareName = name; } public String getAwareName(){ return awareName; }}
我们写一个User类来实现BeanNameAware,重写它的方法setBeanName,并将其赋值给我们的awareName 。
@ComponentScan("com.beans")public class mainT { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(mainT.class); User bean = context.getBean(User.class); System.out.println(bean.getAwareName()); }}
结果显示,得到的bean的名字.
到此这篇关于Spring启动过程源码分析基本概念的文章就介绍到这了,更多相关Spring启动过程内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://www.cnblogs.com/sakela/p/15428553.html 。
最后此篇关于Spring启动过程源码分析及简介的文章就讲到这里了,如果你想了解更多关于Spring启动过程源码分析及简介的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
目录 一、前言 二、『Echarts』简介 1. 什么是『Echarts』 三、数据可视化 四、『Echarts』
Go语言最主要的特性 复制代码 代码如下: 自动垃圾回收 更丰富的内置类型 函数多返回值 错误处理 匿名函数和闭包 类型和接口 并发编程 反射 语言交互性
在ASP中,FSO的意思是File System Object,即文件系统对象。 我们将要操纵的计算机文件系统,在这里是指位于web服务器之上。所以,确认你对此拥有合适的权限。理
Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称。由James Gosling和同事们共同研发,并在1995年正式推出。 Ja
C# 是一个现代的、通用的、面向对象的编程语言,它是由微软(Microsoft)开发的,由 Ecma 和 ISO 核准认可的。 C# 是由 Anders Hejlsberg 和他的团队在 .Net
SQL 是一门 ANSI 的标准计算机语言,用来访问和操作数据库系统。SQL 语句用于取回和更新数据库中的数据。SQL 可与数据库程序协同工作,比如 MS Access、DB2、Informix、M
什么是Apache Storm? Apache Storm是一个分布式实时大数据处理系统。Storm设计用于在容错和水平可扩展方法中处理大量数据。它是一个流数据框架,具有最高的摄取率。虽然Storm
SQLite 简介 本教程帮助您了解什么是 SQLite,它与 SQL 之间的不同,为什么需要它,以及它的应用程序数据库处理方式。 SQLite是一个软件库,实现了自给自足的、无服务器的、零配置的
简介 介绍 很高兴能向大家介绍 Gradle,这是一个基于 JVM 的富有突破性构建工具。 它为您提供了: 一个像 ant 一样,通用的灵活的构建工具 一种可切换的,像 maven
hystrix介绍 Hystrix 供分布式系统使用,提供延迟和容错功能,隔离远程系统、访问和第三方程序库的访问点,防止级联失败,保证复杂的分布系统在面临不可避免的失败时,仍能有其弹性。 hyst
设计模式(Design pattern)是重构解决方案 这点很重要,尤其是现在 B/S 一统天下的局面,过早考虑设计模式,得不偿失 设计模式(Design pattern)代表了最佳的实
Ruby 是一种纯粹的面向对象编程语言。 Ruby 由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)创建于1993年。 Ruby 是 "程序员的最佳朋友&quo
OWL设计的初衷是处理 web 信息 学习 OWL 之前应具备的基础知识 OWL是基于 XML 和 RDF,所以,在我们开始学习 OWL 之前,希望你对 XML、XML 命名空间以及 RDF 有基
资源描述框架(RDF)是用于描述网络资源的 W3C 标准, 比如网页的标题、作者、修改日期、内容以及版权信息 你应当具备的基础知识 在继续学习之前,我们希望你对下面的知识有基本的了解 HT
Perl 像 C 一样强大,像 awk、sed 等脚本描述语言一样方便 Perl 又名实用报表提取语言, 是 Practical Extraction and Report Language 的缩写
AWK是一个命令行工具,它和其它的 Unix/Linux 命令行工具,比如 curl 和 wget 一样,没有界面。 AWK是一门语言,对的,一门语言,而且是一个解释性编程语言。 AWK设计之初就
WSDL 是基于 XML 的用于描述 Web Services 以及如何访问 Web Services 的语言 学习 WSDL 之前应当具备的基础知识 在继续学习之前,我们希望你对下面的知识有基本
我们提供了 Web 版的 JSON 编辑器,你可以依托于我们的 Web 编辑器编辑 JavaScript 代码,然后通过点击一个按钮来查看结果 <!DOCTYPE html> <h
SVG是使用 XML 来描述二维图形和绘图程序的语言, SVG 画出来的图形具有可伸缩不失真的特性 学习之前应具备的基础知识: 继续学习之前,我们应该对以下内容有基本的了解,这样更能方便你了解一些
XML设计的初衷是用来传输和存储数据 继续学习 XML 教程前应该掌握的基础知识 在我们继续学习 XML 之前,希望你对知识有基本的了解 1、 HTML; 2、 JavaScript; 如果你
我是一名优秀的程序员,十分优秀!