SpringloC容器的依赖注入源码解析(3)—— doGetBean之剩余逻辑

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: doGetBean源码:

文章目录


doGetBean源码

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   // 先将方法传入的name转换成容器真实的beanName
   // 之前可以通过三种形式获取beanName
   // 一个是原始的beanName,一个是加了&的,一个是别名
   final String beanName = transformedBeanName(name);
   Object bean;
   // Eagerly check singleton cache for manually registered singletons.
   Object sharedInstance = getSingleton(beanName);
   // 加果先前已经创建过单例Bean的实例,并且调用的getBean方法传入的参数为空,则执行理面的逻辑
   // args之所以要求为空是因为如果有args,则需要做进一步赋值,因此无法直接返回
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         // 如果Bean还在创建中,则说明是循环引用
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      // 如果是普通bean,直接返回,如果是FactoryBean,则返回他的getObject
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }
   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }
      // Check if bean definition exists in this factory.
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);
         }
         else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {
            return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }
      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }
      try {
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);
         // Guarantee initialization of beans that the current bean depends on.
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }
         // Create bean instance.
         // 如果BeanDefinition为单例
         if (mbd.isSingleton()) {
            // 这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
                  // Explicitly remove instance from singleton cache: It might have been put there
                  // eagerly by the creation process, to allow for circular reference resolution.
                  // Also remove any beans that received a temporary reference to the bean.
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }
         else {
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  }
                  finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
                     "Scope '" + scopeName + "' is not active for the current thread; consider " +
                     "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                     ex);
            }
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }
   // Check if required type matches the type of the actual bean instance.
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
         T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return convertedBean;
      }
      catch (TypeMismatchException ex) {
         if (logger.isTraceEnabled()) {
            logger.trace("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}


之前讨论了doGetBean里面从缓存获取bean的代码,doGetBean方法接下来的else处理Bean的scope为prototype或者单例模式但是缓存中还不存在bean的情况:


81.png


Spring同样为scope为prototype的Bean设计了一个缓存列表


if (isPrototypeCurrentlyInCreation(beanName)) {
   throw new BeanCurrentlyInCreationException(beanName);
}


protected boolean isPrototypeCurrentlyInCreation(String beanName) {
   Object curVal = this.prototypesCurrentlyInCreation.get();
   return (curVal != null &&
         (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}

相比单例的set,这里是ThreadLocal,只记录当前线程创建出来的scope为prototype的Bean,上面的if如果是true的话证明有循环依赖。



通过了循环依赖校验之后看容器是否存在父容器,如果存在且当前容器里没有包含此bean的BeanDefinition实例,尝试去从父类容器递归查询



83.png


为了防止之前的beanName已经被转换的不成样子,将&重新加上,再调用父类的doGetBean或者getBean方法,如果父类是AbstractBeanFactory,则调用doGetBean


如果当前容器里包含了此bean的BeanDefinition实例则继续执行


// typeCheckOnly 是用来判断调用 getBean() 是否仅仅是为了类型检查获取 bean,而不是为了创建Bean
if (!typeCheckOnly) {
   // 如果不是仅仅做类型检查则是创建bean
   markBeanAsCreated(beanName);
}


进入markBeanAsCreated方法里,

protected void markBeanAsCreated(String beanName) {
   // 双重检查锁机制
   if (!this.alreadyCreated.contains(beanName)) {
      synchronized (this.mergedBeanDefinitions) {
         if (!this.alreadyCreated.contains(beanName)) {
            // Let the bean definition get re-merged now that we're actually creating
            // the bean... just in case some of its metadata changed in the meantime.
            // 将原先合并之后的RootBeanDefinition的需要重新合并的状态设置为true
            // 表示需要重新合并一遍,以防原数据的改动
            clearMergedBeanDefinition(beanName);
            // 将已经创建好的或者正在创建的Bean的名称加到alreadyCreated这个缓存中
            this.alreadyCreated.add(beanName);
         }
      }
   }
}


有一个双重锁检查机制,创建的Bean的名称加到alreadyCreated(类型Set)这个缓存中,在加入缓存之前需要将原先的MergedBeanDefinition设置上一个需要清除的标识符,目的是让后续从容器中获取BeanDefinition时重新合并子类和父类的BeanDefinition,这样就可以防止元数据被改动后,BeanDefinition还是按照原来的数据去创建


protected void clearMergedBeanDefinition(String beanName) {
   RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName);
   if (bd != null) {
      bd.stale = true;
   }
}


clearMergedBeanDefinition回去容器中获取RootBeanDefinition实例,然后把该实例需要重新合并的状态设为true(之前提到过,只要指定了parent属性,则两个BeanDefinition就合并成一个来使用)


回到doGetBean,接下来会调用getMergedLocalBeanDefinition方法来合并子类和父类的BeanDefinition,进入到该方法里:

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
   // Quick check on the concurrent map first, with minimal locking.
   RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
   if (mbd != null && !mbd.stale) {
      return mbd;
   }
   return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

clearMergedBeanDefinition回去容器中获取RootBeanDefinition实例,然后把该实例需要重新合并的状态设为true(之前提到过,只要指定了parent属性,则两个BeanDefinition就合并成一个来使用)


回到doGetBean,接下来会调用getMergedLocalBeanDefinition方法来合并子类和父类的BeanDefinition,进入到该方法里:


protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
   // Quick check on the concurrent map first, with minimal locking.
   RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
   if (mbd != null && !mbd.stale) {
      return mbd;
   }
   return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}


先从mergedBeanDefinitions缓存里获取之前已经合并好的RootBeanDefinition实例,如果stale为true的话就会合并一遍BeanDefinition,随后返回。


回到doGetBean,获取到了BeanDefinition之后,就去对相关实例做合法性校验

checkMergedBeanDefinition(mbd, beanName, args);

进入到checkMergedBeanDefinition方法里:


protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
      throws BeanDefinitionStoreException {
   if (mbd.isAbstract()) {
      throw new BeanIsAbstractException(beanName);
   }
}


看一下RootBeanDefinition是否是抽象的。


回到doGetBean,尝试从BeanDefinition里获取显式的依赖关系,如果有depends-on的话就检查是否有循环依赖关系


84.png


如果没有循环依赖的话则会将相关的依赖关系注册上

registerDependentBean(dep, beanName);


public void registerDependentBean(String beanName, String dependentBeanName) {
   String canonicalName = canonicalName(beanName);
   synchronized (this.dependentBeanMap) {
      // computeIfAbsent:若key对应的value为空,会将第二个参数的返回值存入并返回
      // dependentBeanMap中存放着当前Bean被引用的Bean的集合
      // 比如当前需要实例化的是Bean的名字是userInfo,userInfo中有个Human类型的属性human
      // 那么就有human被userInfo引用的关系 human=[userInfo]
      Set<String> dependentBeans =
            this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
      if (!dependentBeans.add(dependentBeanName)) {
         return;
      }
   }
   synchronized (this.dependenciesForBeanMap) {
      Set<String> dependenciesForBean =
            this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
      dependenciesForBean.add(canonicalName);
   }
}


先获取name,之后就进入两重注册,第一重注册往dependentBeanMap中写入键值对,key是被依赖的Bean名字,value是依赖他的Bean名字列表



第二重注册往dependenciesForBeanMap中写入键值对,键值对和上面正好是相反的


回到doGetBean,执行完显式依赖关系注册之后就会递归调用getBean(dep)来将依赖的bean创建出来,往后就是根据不同的scope进行不同的创建bean的操作了,分为Singleton、Prototype和其他。



除了Prototype是直接调用createBean(beanName, mbd, args)去创建Bean实例之外,scope=其他的将createBean封装到了一个匿名参数里


85.png进入scope.get()方法


Object get(String name, ObjectFactory<?> objectFactory);


可见后面的匿名函数实现的是ObjectFactory的getObject方法,调用createBean方法去创建适配scope的实例。


下面主要分析scope = singleton的:


if (mbd.isSingleton()) {
   // 这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
   sharedInstance = getSingleton(beanName, () -> {
      try {
         return createBean(beanName, mbd, args);
      }
      catch (BeansException ex) {
         // Explicitly remove instance from singleton cache: It might have been put there
         // eagerly by the creation process, to allow for circular reference resolution.
         // Also remove any beans that received a temporary reference to the bean.
         // 显式从单例缓存中删除 bean实例
         // 因为单例模式下为了解决循环依赖,可能它已经存在了,所以将其销毁
         destroySingleton(beanName);
         throw ex;
      }
   });
   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}


进入getSingleton方法:

86.png


也是接收一个ObjectFactory对象然后实现其getObject方法。


进入createBean:


protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException;


这是个抽象方法需要子类去实现。


再回到上面的getSingleton方法:


public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "Bean name must not be null");
   synchronized (this.singletonObjects) {
      Object singletonObject = this.singletonObjects.get(beanName);
      if (singletonObject == null) {
         if (this.singletonsCurrentlyInDestruction) {
            throw new BeanCreationNotAllowedException(beanName,
                  "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                  "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
         }
         if (logger.isDebugEnabled()) {
            logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
         }
         beforeSingletonCreation(beanName);
         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
            this.suppressedExceptions = new LinkedHashSet<>();
         }
         try {
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }
         catch (IllegalStateException ex) {
            // Has the singleton object implicitly appeared in the meantime ->
            // if yes, proceed with it since the exception indicates that state.
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               throw ex;
            }
         }
         catch (BeanCreationException ex) {
            if (recordSuppressedExceptions) {
               for (Exception suppressedException : this.suppressedExceptions) {
                  ex.addRelatedCause(suppressedException);
               }
            }
            throw ex;
         }
         finally {
            if (recordSuppressedExceptions) {
               this.suppressedExceptions = null;
            }
            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

先将一级缓存singletonObjects上锁,获取到锁之后再次尝试从一级缓存里去获取实例,以防别的线程创建好了,如果获取不到实例就开始做真正的创建了:


先看一下目前容器是否正在销毁所有的单例:


87.png


singletonsCurrentlyInDestruction是个flag。


通过验证之后会来到beforeSingletonCreation(beanName),进入:


protected void beforeSingletonCreation(String beanName) {
    //inCreationCheckExclusions 直接缓存当前不能加载的bean,
    //主要用在web容器的拦截器里,所以这里可以忽略,因为肯定是不存在的
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
   }
}


if 的第一个条件可以忽略,第二个条件是尝试将beanName放入正在创建的单例名字列表里,添加失败则会抛异常,因为bean的正常创建流程按理是进入不到这里的,如果beanName出现在正在创建的名字列表中则表明在本次操作之前对于同一个bean的创建已经在进行了,doGetBean的时候第一步从三级缓存中获取Bean实例的时候就应该已经获取到了。


在并发场景下,两个线程在三级缓存里都没获取到单例,就会来到这里。



再回到上面的getSingleton方法,接下来就可以去创建并获取bean实例了:


88.png

newSingleton设置为true方便后续调用addSingleton来添加一级缓存。


异常处理跳过,看一下finally:


89.png


进入afterSingletonCreation:

protected void afterSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
      throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
   }
}


由于bean实例已经创建完毕了,所以会从正在创建的bean名字列表singletonsCurrentlyInCreation中移除beanName


回到外面,接下来就会去判断是否是新创建的单例,之前标志位已经是true了,进入addSingleton:


protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      // Bean实例完成创建之后,只保留一级缓存以及注册beanName的顺序,其余的清除
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}


执行完addSingleton之后就会返回完整的bean实例了


回到doGetBean的创建单例的逻辑中,返回完整的bean实例之后就会执行


// 如果是普通bean,直接返回,是FactoryBean,返回他的getObject
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);


再看下scope为Prototype的创建:

90.png


进入beforePrototypeCreation:

protected void beforePrototypeCreation(String beanName) {
   Object curVal = this.prototypesCurrentlyInCreation.get();
   if (curVal == null) {
      this.prototypesCurrentlyInCreation.set(beanName);
   }
   else if (curVal instanceof String) {
      Set<String> beanNameSet = new HashSet<>(2);
      beanNameSet.add((String) curVal);
      beanNameSet.add(beanName);
      this.prototypesCurrentlyInCreation.set(beanNameSet);
   }
   else {
      Set<String> beanNameSet = (Set<String>) curVal;
      beanNameSet.add(beanName);
   }
}


向类型为ThreadLocal的prototypesCurrentlyInCreation(当前线程正在创建的Prototype的bean名字列表)去添加该bean的记录,防止循环依赖,表示这个bean正在创建中。



回到doGetBean,之后也调用了prototypeInstance = createBean(beanName, mbd, args),创建完之后将先前注册的正在创建中的Bean信息给抹除掉


afterPrototypeCreation(beanName);
protected void afterPrototypeCreation(String beanName) {
   Object curVal = this.prototypesCurrentlyInCreation.get();
   if (curVal instanceof String) {
      this.prototypesCurrentlyInCreation.remove();
   }
   else if (curVal instanceof Set) {
      Set<String> beanNameSet = (Set<String>) curVal;
      beanNameSet.remove(beanName);
      if (beanNameSet.isEmpty()) {
         this.prototypesCurrentlyInCreation.remove();
      }
   }
}

回到doGetBean,之后也会调用


bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);


获取bean实例或者beanFactory创建的bean实例


最后在看其他的情况,


91.png


根据生命周期范围选择实例化bean的合适方法来创建bean实例,比如request就是确保每个请求生成一个实例。


doGetBean最后会做一个类型检查,校验通过后返回实例:


if (requiredType != null && !requiredType.isInstance(bean)) {
   try {
      T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
      if (convertedBean == null) {
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
      return convertedBean;
   }
   catch (TypeMismatchException ex) {
      if (logger.isTraceEnabled()) {
         logger.trace("Failed to convert bean '" + name + "' to required type '" +
               ClassUtils.getQualifiedName(requiredType) + "'", ex);
      }
      throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
   }
}
return (T) bean;



相关文章
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
87 2
|
10天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
10天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
10天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
10天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2月前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
57 12
|
29天前
|
PyTorch Shell API
Ascend Extension for PyTorch的源码解析
本文介绍了Ascend对PyTorch代码的适配过程,包括源码下载、编译步骤及常见问题,详细解析了torch-npu编译后的文件结构和三种实现昇腾NPU算子调用的方式:通过torch的register方式、定义算子方式和API重定向映射方式。这对于开发者理解和使用Ascend平台上的PyTorch具有重要指导意义。
|
1月前
|
负载均衡 网络协议 算法
Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式
本文探讨了Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式,以及软件负载均衡器、云服务负载均衡、容器编排工具等实现手段,强调两者结合的重要性及面临挑战的应对措施。
75 3
|
10天前
|
安全 搜索推荐 数据挖掘
陪玩系统源码开发流程解析,成品陪玩系统源码的优点
我们自主开发的多客陪玩系统源码,整合了市面上主流陪玩APP功能,支持二次开发。该系统适用于线上游戏陪玩、语音视频聊天、心理咨询等场景,提供用户注册管理、陪玩者资料库、预约匹配、实时通讯、支付结算、安全隐私保护、客户服务及数据分析等功能,打造综合性社交平台。随着互联网技术发展,陪玩系统正成为游戏爱好者的新宠,改变游戏体验并带来新的商业模式。
|
2月前
|
安全 持续交付 Docker
深入理解并实践容器化技术——Docker 深度解析
深入理解并实践容器化技术——Docker 深度解析
67 2

推荐镜像

更多