九.DefaultBootstrapContext类分析

该类实现了ConfigurableBootstrapContext接口,因此具有ConfigurableBootstrapContext的所有功能。

该类中有三个属性:   

//存放InstanceSupplier对象,该对象用来获取实际对象,也就是说用该对象创建实际对象

private final Map<Class<?>, InstanceSupplier<?>> instanceSuppliers = new HashMap<>();

//存放实际的单例对象

private final Map<Class<?>, Object> instances = new HashMap<>();

//事件广播器

private final ApplicationEventMulticaster events = new SimpleApplicationEventMulticaster();

//向注册表注册特定类型。如果指定的类型已注册,但尚未作为单例获得,则将替换它。

@Override

public <T> void register(Class<T> type, InstanceSupplier<T> instanceSupplier) {

  register(type, instanceSupplier, true);

}

//如果尚未注册特定类型,请向注册表注册该类型。

@Override

public <T> void registerIfAbsent(Class<T> type, InstanceSupplier<T> instanceSupplier) {

  register(type, instanceSupplier, false);

}

//实际执行的注册方法

private <T> void register(Class<T> type, InstanceSupplier<T> instanceSupplier, boolean replaceExisting) {

  Assert.notNull(type, "Type must not be null");

  Assert.notNull(instanceSupplier, "InstanceSupplier must not be null");

 //加锁,有可能有多个线程同时操作注册中心,而Map类型是线程不安全的,所以需要加锁

  synchronized (this.instanceSuppliers) {

//判断instanceSuppliers 注册表中是否存在该类型

      boolean alreadyRegistered = this.instanceSuppliers.containsKey(type);

 //如果需要用新的值替换旧的值或者该类型在注册表中不存在,那么向注册表中注册该特定类型。

      if (replaceExisting || !alreadyRegistered) {

        Assert.state(!this.instances.containsKey(type), () -> type.getName() + " has already been created");

        this.instanceSuppliers.put(type, instanceSupplier);

      }

  }

}

// 如果给定类型存在注册,则返回true,否则返回false

@Override

public <T> boolean isRegistered(Class<T> type) {

 //有可能有多个线程同时操作注册中心,而Map类型是线程不安全的,所以需要加锁

  synchronized (this.instanceSuppliers) {

//判断指定类型是否存在

      return this.instanceSuppliers.containsKey(type);

  }

}

//返回给定类型的任何现有InstanceSupplier

@Override

@SuppressWarnings("unchecked")

public <T> InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type) {

 //有可能有多个线程同时操作注册中心,而Map类型是线程不安全的,所以需要加锁

  synchronized (this.instanceSuppliers) {

   // 返回给定类型的任何现有InstanceSupplier

      return (InstanceSupplier<T>) this.instanceSuppliers.get(type);

  }

}

// 添加一个ApplicationListener,当BootstrapContext关闭且ApplicationContext已准备好时,将使用BootstrapContextClosedEvent调用它。

// 可用于添加一个监听器,该监听器可在BootstrapContext已关闭且ApplicationContext已完全准备好时执行操作。例如,一个实例可以选择将自己注册为一个普通的Springbean,以便应用程序可以使用它。

@Override

public void addCloseListener(ApplicationListener listener) {

     this.events.addApplicationListener(listener);

}

// 如果类型已注册,则从上下文返回实例。如果以前没有访问过该实例,则将创建该实例。

public <T> T get(Class<T> type) throws IllegalStateException {

  return getOrElseThrow(type, () -> new IllegalStateException(type.getName() + " has not been registered"));

}

// 如果类型已注册,则从上下文返回实例。如果以前没有访问过该实例,则将创建该实例。如果类型没有被注册,则返回指定的其他实例。

@Override

public <T> T getOrElse(Class<T> type, T other) {

           return getOrElseSupply(type, () -> other);

}

//如果类型已注册,则从上下文返回实例。如果以前没有访问过该实例,则将创建该实例。如果类型没注册通过Supplier新建一个对象实例。

@Override

public <T> T getOrElseSupply(Class<T> type, Supplier<T> other) {

//加锁,有可能有多个线程同时操作注册中心,而Map类型是线程不安全的,所以需要加锁

  synchronized (this.instanceSuppliers) {

      //从InstanceSupplier注册表中获取InstanceSupplier实例

      InstanceSupplier<?> instanceSupplier = this.instanceSuppliers.get(type);

 //如果该类型在注册表中存在,则获取该类型的实例,否则返回该类型指定的其他实例。

      return (instanceSupplier != null) ? getInstance(type, instanceSupplier) : other.get();

  }

}

// 如果类型已注册,则从上下文返回实例。如果以前没有访问过该实例,则将创建该实例。如果类型没有注册则抛出异常。

@Override

public <T, X extends Throwable> T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier) throws X {

//加锁,有可能有多个线程同时操作注册中心,而Map类型是线程不安全的,所以需要加锁

  synchronized (this.instanceSuppliers) {

     //从InstanceSupplier注册表中获取InstanceSupplier实例

      InstanceSupplier<?> instanceSupplier = this.instanceSuppliers.get(type);

     // 如果该类型没有注册,抛出指定异常

      if (instanceSupplier == null) {

        throw exceptionSupplier.get();

      }

      return getInstance(type, instanceSupplier);

  }

}

//获取指定类型的实例

@SuppressWarnings("unchecked")

private T getInstance(Class type, InstanceSupplier instanceSupplier) {

       // 从实例注册表中获取该类型对应的实例

        T instance = (T)this.instances.get(type);

           //如果实例注册表中不存在该实例

           if (instance ==null) {

                //从该类型对应的实例工厂中获取该类型的实例

                instance = (T) instanceSupplier.get(this);

                //判断该类型是不是单例,如果是单例的化,将该类型对应的实例存放到实例注册表中

                if (instanceSupplier.getScope() == Scope.SINGLETON) {

                this.instances.put(type, instance);

              }

}

        return instance;

}

// 发布关闭BootstrapContext并准备ApplicationContext的事件

// 方法在关闭BootstrapContext并准备ApplicationContext时调用。

public void close(ConfigurableApplicationContext applicationContext) {

        this.events.multicastEvent(new BootstrapContextClosedEvent(this, applicationContext));

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容