当前位置: 移动技术网 > IT编程>开发语言>Java > 关于Spring启动时Context加载源码分析

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

2019年07月19日  | 移动技术网IT编程  | 我要评论

前言

本文主要给大家介绍了关于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);
}

此过程的调用栈:

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

总结

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网