• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

哈士兔也被占用?

java相关技术知识总结,分享。。。。。。
  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

springboot源码(四)

springboot入口run方法细节分析

 上一篇主要说了一下SpringApplication的构造方法和 run 方法里面都做了哪些事情,这一篇具体分析一下里面的主要方法。

1、//将spring.factories中key为ApplicationContextInitializer对应的类型实例化后放到成员变量initializers里
   this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

分析一下该方法:

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = getClassLoader();
        // type=ApplicationContextInitializer  加载spring.factories中key为ApplicationContextInitializer,将全类路径名存放到names中
        Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 根据names中的全类路径名创建实例 List
<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }

 

 

private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
            ClassLoader classLoader, Object[] args, Set<String> names) {
        List<T> instances = new ArrayList<>(names.size());
        for (String name : names) {
            try {
//通过反射的方式得到类 Class
<?> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass);
//创建构造器进行实例化 Constructor
<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes); T instance = (T) BeanUtils.instantiateClass(constructor, args); instances.add(instance); } catch (Throwable ex) { throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex); } } return instances; }

 

 

2、//将spring.factories中key为ApplicationListener的对应类型实例化后放到SpringApplication的成员变量listener里
   this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

分析一下:

大致过程跟setInitializers()方法是一样的,就是把spring.factories中的ApplicationListener的对应类型的实例化放到SpringApplication的成员变量listeners中。

 

 

3、//反推main方法所在的类对象,并记录在mainApplicationClass中
      this.mainApplicationClass = this.deduceMainApplicationClass();

分析一下如何反推回main方法所在的class对象的:

StackTrace:

      我们在学习函数调用时,就知道了每个函数都拥有自己的栈空间。

      一个函数被调用时,就创建一个新的栈空间,那么通过函数的嵌套调用最后就形成了一个函数调用堆栈。

     所以,StackTrace就是记录了程序方法执行的链路。

debug形式查看函数调用栈:

 

 

private Class<?> deduceMainApplicationClass() {
        try {
//获取当前方法执行的堆栈信息 StackTraceElement[] stackTrace
= new RuntimeException().getStackTrace(); for (StackTraceElement stackTraceElement : stackTrace) {
//判断是否是main方法,如果是返回main方法对应的class对象
if ("main".equals(stackTraceElement.getMethodName())) { return Class.forName(stackTraceElement.getClassName()); } } } catch (ClassNotFoundException ex) { // Swallow and continue } return null; }

 

 

 

 

4、分析run方法中的比较重要的方法

 //加载SpringApplicationRunListener得到事件发布器EventPublishingRunListener,会把SpingringApplication中的成员变量listener放到listeners中
 SpringApplicationRunListeners listeners = this.getRunListeners(args);
private SpringApplicationRunListeners getRunListeners(String[] args) {
//声明了一个参数类型数组,其中有一个是SpringApplication类型 Class
<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
//将参数数组types作为参数传递给很熟悉的getSpringFactoriesInstances()方法
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)); }
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = getClassLoader();
        // 加载spring.factories中SpringApplicationRunListener类型:EventPublishingRunListener(事件发布器)
        Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//创建EventPublishingRunlistener实例 List
<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
            ClassLoader classLoader, Object[] args, Set<String> names) {
        List<T> instances = new ArrayList<>(names.size());
        for (String name : names) {
            try {
                Class<?> instanceClass = ClassUtils.forName(name, classLoader);
                Assert.isAssignable(type, instanceClass);
//EventPublishingRunlistener的构造器参数分别为SpringApplication和String[],所以EventPublishingRunListener事件发布器就加载到所有SpringApplication中listeners变量中的全部ApplicationListener Constructor
<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes); T instance = (T) BeanUtils.instantiateClass(constructor, args); instances.add(instance); } catch (Throwable ex) { throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex); } } return instances; }

 

//EventPublishingRunlistener类源码
public
class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SpringApplication application; private final String[] args; private final SimpleApplicationEventMulticaster initialMulticaster; public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.initialMulticaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } }

 


到这,基本上就知道了run方法都大致干了些什么勾当。下一篇分析springboot监听器的设计。


萝莉身,御姐心。。。。。

posted on 2022-03-29 01:52  哈士兔也被占用?  阅读(40)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3