评论

收藏

[Java] Spring IOC基于注解启动示例详析

编程语言 编程语言 发布于:2021-09-18 15:46 | 阅读数:306 | 评论:0

这篇文章主要给大家介绍了Spring IOC基于注解启动的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
spring 基于注解启动
主要有两个class实现注解启动

  • annotationconfigapplicationcontext
  • annotationconfigwebapplicationcontext
我们以annotationconfigapplicationcontext 为研究对象
DSC0000.jpg
annotationconfigapplicationcontext.png

引入spring 最小依赖
<dependency>
 <groupid>org.springframework</groupid>
 <artifactid>spring-context</artifactid>
 <version>${spring.version}</version>
</dependency>
编写器启动代码
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 构造函数
public annotationconfigapplicationcontext() {
   //负责注册class ,读取器
 this.reader = new annotatedbeandefinitionreader(this);
   //负责扫描指定类路径下的class,注册bean
 this.scanner = new classpathbeandefinitionscanner(this);
}
annotatedbeandefinitionreader 构造方法
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 这个对象干什么,点击进去
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构造函数
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)
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来实现
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      用户自定义bean
spring 启动流程总结
DSC0001.jpg

annotationconfigapplicationcontext 初始化.png
这些beandefinition只是放入到spirng 容器中,并没有进行任何初始化对象的操作,真正的ioc操作都在refresh(),这个方法有空再进行分析。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对CodeAE代码之家的支持。
原文链接:https://www.jianshu.com/p/573bdae020e9

关注下面的标签,发现更多相似文章