欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

关于Spring启动时Context加载源码分析

程序员文章站 2023-12-12 13:12:58
前言 本文主要给大家介绍了关于spring启动时context加载的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 测试源码下载 有如...

前言

本文主要给大家介绍了关于spring启动时context加载的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

测试源码下载

有如下的代码

@component
public class helloworldservice {
 @value("${name:world}")
 private string name;
 public string gethellomessage() {
 return "hello " + this.name;
 }
}

@configuration
public class bootstrap {
 @bean
 public static helloworldservice helloservice() {
 return new helloworldservice();
 }
 public static void main(string[] args) {
 instantiationstrategy instantiationstrategy = new simpleinstantiationstrategy();
 defaultlistablebeanfactory beanfactory = new defaultlistablebeanfactory();
 beanfactory.setinstantiationstrategy(instantiationstrategy);
 annotationconfigapplicationcontext applicationcontext = 
 new annotationconfigapplicationcontext(beanfactory);
 applicationcontext.register(bootstrap.class);
 applicationcontext.refresh();
 helloworldservice service = applicationcontext.getbean(helloworldservice.class);
 system.out.println(service.gethellomessage());
 applicationcontext.close();
 }
}

helloworldservice.gethellomessage方法简单的返回name的值, bootstrap.main方法中使用annotationconfigapplicationcontext 构造一个上下文对象, 为了演示的方便, 显示的声明了defaultlistablebeanfactory和instantiationstrategy实例。通过applicationcontext.getbean()获取bean的引用,并调用 service.gethellomessage() 方法。

上下文的加载主要发生在applicationcontext.register方法和applicationcontext.refresh方法中,
applicationcontext.register方法的作用是为参数(使用@configuration注解的class)生成beandefinition 对象并调用defaultlistablebeanfactory.registerbeandefinition将beandefinition注册到defaultlistablebeanfactory中。

applicationcontext.refresh()的功能要更多,主要功能一的是调用postprocessor为@configuration类中的@bean标注的方法生成对应的beandefinition对象,并注册到defaultlistablebeanfactory中,功能二是遍历defaultlistablebeanfactory中beandefinition, 产生真正的对象。

为@configuration类中@bean标注的方法生成beandefinition对象详细过程如下

步骤1、找到合适的beandefinitionregistrypostprocessor处理器

org.springframework.context.support.postprocessorregistrationdelegate.invokebeanfactorypostprocessors() {
 ...
 //获取适用的beandefinitionregistrypostprocessor bean名称
 string[] postprocessornames =
  beanfactory.getbeannamesfortype(beandefinitionregistrypostprocessor.class, true, false);
 ...
 //根据beanname获取postprocessor, 处理@configuration标注类的beanname为
 //org.springframework.context.annotation.internalconfigurationannotationprocessor 
 //实现为org.springframework.context.annotation.configurationclasspostprocessor
 configurationclasspostprocessor postprocessor =beanfactory.getbean(postprocessornames[0], beandefinitionregistrypostprocessor.class)
}

步骤2、为@configuration产生configurationclass对象

//使用configurationclassparser解析@configuration标注的类,

//每一个@configuration标注的类产生一个configurationclass对象,

//configurationclass.getbeanmethods()能获得该类中所有使用@bean标注的方法,

//@bean标注的方法使用beanmethod对象表示

org.springframework.context.annotation.configurationclasspostprocessor.processconfigbeandefinitions(beandefinitionregistry registry) {
 configurationclassparser parser = new configurationclassparser(
 this.metadatareaderfactory, this.problemreporter, this.environment,
 this.resourceloader, this.componentscanbeannamegenerator, registry);
 parser.parse(configcandidates);
 parser.validate();
 this.reader.loadbeandefinitions(parser.getconfigurationclasses());
}

步骤3、@bean标注的方法产生beandefinition并注入到defaultlistablebeanfactory中

org.springframework.context.annotation.configurationclassbeandefinitionreader.loadbeandefinitionsforbeanmethod(beanmethod beanmethod) {
 configurationclassbeandefinition beandef = new configurationclassbeandefinition(configclass);
 beandef.setbeanclassname(configclass.getmetadata().getclassname());
 beandef.setfactorymethodname(metadata.getmethodname());
 //registry 是defaultlistablebeanfactory的实例
 this.registry.registerbeandefinition(beanname, beandeftoregister);
}

此过程的调用栈:

关于Spring启动时Context加载源码分析

根据beandefinition生成实例过程的调用栈:

关于Spring启动时Context加载源码分析

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

上一篇:

下一篇: