关于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); }
此过程的调用栈:
根据beandefinition生成实例过程的调用栈:
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。