spring 基于注解启动
主要有两个class实现注解启动
annotationconfigapplicationcontext annotationconfigwebapplicationcontext我们以annotationconfigapplicationcontext 为研究对象
annotationconfigapplicationcontext.png
引入spring 最小依赖
1 2 3 4 5 |
<dependency> <groupid>org.springframework</groupid> <artifactid>spring-context</artifactid> <version>${spring.version}</version> </dependency> |
编写器启动代码
1 2 3 4 5 6 7 |
public static void main(string[] args) { annotationconfigapplicationcontext applicationcontext = new annotationconfigapplicationcontext(); applicationcontext.register(beanconfig. class ); applicationcontext.refresh(); date date = applicationcontext.getbean( "date" ,date. class ); system.out.println(date); } |
annotationconfigapplicationcontext 构造函数
1 2 3 4 5 6 |
public annotationconfigapplicationcontext() { //负责注册class ,读取器 this .reader = new annotatedbeandefinitionreader( this ); //负责扫描指定类路径下的class,注册bean this .scanner = new classpathbeandefinitionscanner( this ); } |
annotatedbeandefinitionreader 构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public annotatedbeandefinitionreader(beandefinitionregistry registry) { this (registry, getorcreateenvironment(registry)); }
public annotatedbeandefinitionreader(beandefinitionregistry registry, environment environment) { assert .notnull(registry, "beandefinitionregistry must not be null" ); assert .notnull(environment, "environment must not be null" ); this .registry = registry; //初始化conditionevaluator this .conditionevaluator = new conditionevaluator(registry, environment, null );
/** 在給定的注册表中註冊所有相关的post processors * 判断容器是否已经存在给定注册表的bean,如果没有注册bean,并将bean放入容器中 * 把所有的处理处理器列出来 * configurationclasspostprocessor 內部管理的配置注解处理器 * autowiredannotationbeanpostprocessor 内部管理@autowired 的处理器 * requiredannotationbeanpostprocessor @required的处理器 * commonannotationbeanpostprocessor jsr-250注解处理器 ,先判断是否支持jsr,如果支持注册 * persistenceannotationbeanpostprocessor jpa管理 先使用类加载器查找是否存在,如果有这个包则注册 * eventlistenermethodprocessor @eventlistener的处理器 * defaulteventlistenerfactory 管理eventlistenerfactory处理器 */ annotationconfigutils.registerannotationconfigprocessors( this .registry); } |
conditionevaluator 这个对象干什么,点击进去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public conditionevaluator( @nullable beandefinitionregistry registry, @nullable environment environment, @nullable resourceloader resourceloader) {
this .context = new conditioncontextimpl(registry, environment, resourceloader); } //conditioncontextimpl 实现了conditioncontext接口,conditionevaluator静态内部类 public conditioncontextimpl( @nullable beandefinitionregistry registry, @nullable environment environment, @nullable resourceloader resourceloader) {
this .registry = registry; this .beanfactory = deducebeanfactory(registry); this .environment = (environment != null ? environment : deduceenvironment(registry)); this .resourceloader = (resourceloader != null ? resourceloader : deduceresourceloader(registry)); this .classloader = deduceclassloader(resourceloader, this .beanfactory); } |
可以知道conditionevaluator使用外部传参的方法初始化了spring容器顶级对象
beanfactory,environment,resourceloader,classloader。在将这些传给conditioncontextimpl为接下来的解析@conditional注解做好准备
classpathbeandefinitionscanner构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
public classpathbeandefinitionscanner(beandefinitionregistry registry) { this (registry, true ); }
public classpathbeandefinitionscanner(beandefinitionregistry registry, boolean usedefaultfilters) { this (registry, usedefaultfilters, getorcreateenvironment(registry)); }
public classpathbeandefinitionscanner(beandefinitionregistry registry, boolean usedefaultfilters, environment environment) { this (registry, usedefaultfilters, environment, (registry instanceof resourceloader ? (resourceloader) registry : null )); }
public classpathbeandefinitionscanner(beandefinitionregistry registry, boolean usedefaultfilters, environment environment, @nullable resourceloader resourceloader) { assert .notnull(registry, "beandefinitionregistry must not be null" ); this .registry = registry; if (usedefaultfilters) { registerdefaultfilters(); } setenvironment(environment); setresourceloader(resourceloader); }
protected void registerdefaultfilters() { this .includefilters.add( new annotationtypefilter(component. class )); classloader cl = classpathscanningcandidatecomponentprovider. class .getclassloader(); try { this .includefilters.add( new annotationtypefilter( (( class <? extends annotation>) classutils.forname( "javax.annotation.managedbean" , cl)), false )); logger.debug( "jsr-250 'javax.annotation.managedbean' found and supported for component scanning" ); } catch (classnotfoundexception ex) { } try { this .includefilters.add( new annotationtypefilter( (( class <? extends annotation>) classutils.forname( "javax.inject.named" , cl)), false )); logger.debug( "jsr-330 'javax.inject.named' annotation found and supported for component scanning" ); } catch (classnotfoundexception ex) { // jsr-330 api not available - simply skip. } } |
绕了地球几圈了,其实就是将spring 顶级接口 environment,resourceloader赋值,使用默认注解过滤器,首先将@component加入list中,判断当前环境是否支持jsr-250,jsr-330,相应加入过滤器中。也就是这个扫描器默认只扫描@component或者jsr-250,jsr-330的标记的class。
applicationcontext.register(beanconfig.class)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public void register( class <?>... annotatedclasses) { assert .notempty(annotatedclasses, "at least one annotated class must be specified" ); this .reader.register(annotatedclasses); //调用 刚刚初始化读取器 } | ============================annotatedbeandefinitionreader 读取器代码====================================================================================================== public void register( class <?>... annotatedclasses) { for ( class <?> annotatedclass : annotatedclasses) { registerbean(annotatedclass); } }
public void registerbean( class <?> annotatedclass) { doregisterbean(annotatedclass, null , null , null ); }
/** *从给定的bean解析class给定的注解,执行相应的初始化,保存到spring容器中 */ <t> void doregisterbean( class <t> annotatedclass, @nullable supplier<t> instancesupplier, @nullable string name, @nullable class <? extends annotation>[] qualifiers, beandefinitioncustomizer... definitioncustomizers) {
//根据class的annotated 得出元数据 annotationmetadata annotatedgenericbeandefinition abd = new annotatedgenericbeandefinition(annotatedclass); /** * 判断注册的class 是否包含@conditional注解,如果有获取全部value,放入list中 * 排序后,遍历所有的conditiion的实现,使用反射获取对象,执行matches方法, * 如果发现有返回false,中断循环直接返回true, */ if ( this .conditionevaluator.shouldskip(abd.getmetadata())) { //如果 @conditional条件不满足,不进行注册 return ; }
abd.setinstancesupplier(instancesupplier); //解析class是否有@scope,解析@scope注解返回scopemetadata对象,没有直接返回空 scopemetadata scopemetadata = this .scopemetadataresolver.resolvescopemetadata(abd); abd.setscope(scopemetadata.getscopename()); //判断注解上value是否有值,有就使用这个作为beanname,没有则取类名 string beanname = (name != null ? name : this .beannamegenerator.generatebeanname(abd, this .registry)); //继续解析annotationmetadata的@lazy,@primary,@dependson,@role,@description的注解,放入结果放入对象的属性中 annotationconfigutils.processcommondefinitionannotations(abd); //这个类只是beandefinition 包装类 beandefinitionholder definitionholder = new beandefinitionholder(abd, beanname); //是否需要代理类,如果是则修改内部属性,重新生成beandefinition 对象 definitionholder = annotationconfigutils.applyscopedproxymode(scopemetadata, definitionholder, this .registry); //调用defaultlistablebeanfactory.registerbeandefinition的方法,做一些安全性校验再,将definitionholder 放入register容器中 beandefinitionreaderutils.registerbeandefinition(definitionholder, this .registry); } |
这个方法就是将注册的bean,解析class上的注解,初始化注解数据,做相应处理,转化成beandefinition ,放入spring 容器中保存起来。
我们看下beandefinition是怎么实现注册到spring的容器中,主要由defaultlistablebeanfactory.registerbeandefinition来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
public void registerbeandefinition(string beanname, beandefinition beandefinition) throws beandefinitionstoreexception {
assert .hastext(beanname, "bean name must not be empty" ); assert .notnull(beandefinition, "beandefinition must not be null" );
if (beandefinition instanceof abstractbeandefinition) { try { //对beandefinition 进行校验判断methodoverrides不能为空,必须拥有工厂方法 ((abstractbeandefinition) beandefinition).validate(); } catch (beandefinitionvalidationexception ex) { throw new beandefinitionstoreexception(beandefinition.getresourcedescription(), beanname, "validation of bean definition failed" , ex); } }
beandefinition oldbeandefinition;
oldbeandefinition = this .beandefinitionmap.get(beanname); if (oldbeandefinition != null ) { //这个方法是判断是否允许出现重名bean,并且是不同的定义bean,是否可以覆盖前者 if (!isallowbeandefinitionoverriding()) { throw new beandefinitionstoreexception(beandefinition.getresourcedescription(), beanname, "cannot register bean definition [" + beandefinition + "] for bean '" + beanname + "': there is already [" + oldbeandefinition + "] bound." ); } else if (oldbeandefinition.getrole() < beandefinition.getrole()) { // e.g. was role_application, now overriding with role_support or role_infrastructure if ( this .logger.iswarnenabled()) { this .logger.warn( "overriding user-defined bean definition for bean '" + beanname + "' with a framework-generated bean definition: replacing [" + oldbeandefinition + "] with [" + beandefinition + "]" ); } } else if (!beandefinition.equals(oldbeandefinition)) { if ( this .logger.isinfoenabled()) { this .logger.info( "overriding bean definition for bean '" + beanname + "' with a different definition: replacing [" + oldbeandefinition + "] with [" + beandefinition + "]" ); } } else { if ( this .logger.isdebugenabled()) { this .logger.debug( "overriding bean definition for bean '" + beanname + "' with an equivalent definition: replacing [" + oldbeandefinition + "] with [" + beandefinition + "]" ); } } this .beandefinitionmap.put(beanname, beandefinition); } else { //调用alreadycreated.isempty(),alreadycreated set对象,保存已经创建beanname //文档中表示created,跟这里注册应该不是同一个行为,这个要看到后面才知道什么意思 if (hasbeancreationstarted()) { synchronized ( this .beandefinitionmap) { //更新数据 this .beandefinitionmap.put(beanname, beandefinition); list<string> updateddefinitions = new arraylist<>( this .beandefinitionnames.size() + 1 ); updateddefinitions.addall( this .beandefinitionnames); updateddefinitions.add(beanname); this .beandefinitionnames = updateddefinitions; if ( this .manualsingletonnames.contains(beanname)) { set<string> updatedsingletons = new linkedhashset<>( this .manualsingletonnames); updatedsingletons.remove(beanname); this .manualsingletonnames = updatedsingletons; } } } else { //spring beandefinition 容器,一个map转载 this .beandefinitionmap.put(beanname, beandefinition); //保存beanname,主要用于记录每个bean注册顺序 this .beandefinitionnames.add(beanname); //删除单例,注册成一个普通bean this .manualsingletonnames.remove(beanname); } this .frozenbeandefinitionnames = null ; }
if (oldbeandefinition != null || containssingleton(beanname)) { //更新spring容器里beanname resetbeandefinition(beanname); } } |
将beandefinition注册到spring容器中,并没有太多复杂的逻辑,只是做一些安全性的检查。
beandefinition
一个beandefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。beandefinition仅仅是一个最简单的接口,主要功能是允许beanfactorypostprocessor 例如propertyplaceholderconfigure 能够检索并修改属性值和别的bean的元数据(译注)
spring 容器beandefinition主要分为rootbeandefinition,annotatedgenericbeandefinition这两种
rootbeandefinition spring factory中的特定bean annotatedgenericbeandefinition 用户自定义beanspring 启动流程总结
annotationconfigapplicationcontext 初始化.png
这些beandefinition只是放入到spirng 容器中,并没有进行任何初始化对象的操作,真正的ioc操作都在refresh(),这个方法有空再进行分析。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
原文链接:https://HdhCmsTestjianshu测试数据/p/573bdae020e9
查看更多关于Spring IOC基于注解启动示例详析的详细内容...