Spring源码解析 - FactoryBean&&BeanFactory(中)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Spring源码解析 - FactoryBean&&BeanFactory

关注的是resolveNamedBean方法:

  @SuppressWarnings("unchecked")
  @Nullable
  private <T> NamedBeanHolder<T> resolveNamedBean(
      ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
    Assert.notNull(requiredType, "Required type must not be null");
    String[] candidateNames = getBeanNamesForType(requiredType);
    if (candidateNames.length > 1) {
      List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
      for (String beanName : candidateNames) {
        if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
          autowireCandidates.add(beanName);
        }
      }
      if (!autowireCandidates.isEmpty()) {
        candidateNames = StringUtils.toStringArray(autowireCandidates);
      }
    }
    if (candidateNames.length == 1) {
      String beanName = candidateNames[0];
      return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
    }
    else if (candidateNames.length > 1) {
      Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
      for (String beanName : candidateNames) {
        if (containsSingleton(beanName) && args == null) {
          Object beanInstance = getBean(beanName);
          candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
        }
        else {
          candidates.put(beanName, getType(beanName));
        }
      }
      String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
      if (candidateName == null) {
        candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
      }
      if (candidateName != null) {
        Object beanInstance = candidates.get(candidateName);
        if (beanInstance == null || beanInstance instanceof Class) {
          beanInstance = getBean(candidateName, requiredType.toClass(), args);
        }
        return new NamedBeanHolder<>(candidateName, (T) beanInstance);
      }
      if (!nonUniqueAsNull) {
        throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
      }
    }
    return null;
  }
  @SuppressWarnings("unchecked")
  @Nullable
  private <T> NamedBeanHolder<T> resolveNamedBean(
      ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
    Assert.notNull(requiredType, "Required type must not be null");
    // 该方法根据传入的Class类型获取BeanName,因为有接口有多个实现类情况,所以这里返回是String数组。
    // 调用getBean方法传入的type为com.javaedge.FactoryBeanService类型,但没有在Spring容器中注入FactoryBeanService类型的Bean
    // 所以讲道理在这里应该获取不到beanName,事实是这样吗?看对getBeanNamesForType的分析
    String[] candidateNames = getBeanNamesForType(requiredType);
    // 有多个BeanName,则挑最合适的
    if (candidateNames.length > 1) {
      List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
      for (String beanName : candidateNames) {
        if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
          autowireCandidates.add(beanName);
        }
      }
      if (!autowireCandidates.isEmpty()) {
        candidateNames = StringUtils.toStringArray(autowireCandidates);
      }
    }
    // 如果只有一个BeanName,调用getBean获取Bean实例放到NamedBeanHolder
    // todo
    if (candidateNames.length == 1) {
      String beanName = candidateNames[0];
      return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
    }
    // 经过挑选后,如果合适的BeanName还是多个
    else if (candidateNames.length > 1) {
      Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
      for (String beanName : candidateNames) {
        // 看看是不是已经创建过的单例Bean
        if (containsSingleton(beanName) && args == null) {
          Object beanInstance = getBean(beanName);
          candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
        }
        else {
          // 调用getType继续获取Bean实例
          candidates.put(beanName, getType(beanName));
        }
      }
      // 有多个Bean实例,则取带有Primary注解或者带有Primary信息的
      String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
      if (candidateName == null) {
        // 如果没有Primary注解或者Primary相关的信息,则取优先级高的Bean
        candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
      }
      if (candidateName != null) {
        Object beanInstance = candidates.get(candidateName);
        // Class类型的话 继续调用getBean获取Bean实例
        if (beanInstance == null || beanInstance instanceof Class) {
          beanInstance = getBean(candidateName, requiredType.toClass(), args);
        }
        return new NamedBeanHolder<>(candidateName, (T) beanInstance);
      }
      if (!nonUniqueAsNull) {
        // 都没获取到,抛出异常
        throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
      }
    }
    return null;
  }

上面的代码中我们传入的type是com.javaedge.FactoryBeanService类型,但是在我们的Spring容器中却没有FactoryBeanService类型的Bean,那么我们是怎么从getBeanNamesForType获取到beanName的?


getBeanNamesForType


image.png

目录
相关文章
|
8天前
|
负载均衡 算法 Java
Spring Cloud全解析:负载均衡算法
本文介绍了负载均衡的两种方式:集中式负载均衡和进程内负载均衡,以及常见的负载均衡算法,包括轮询、随机、源地址哈希、加权轮询、加权随机和最小连接数等方法,帮助读者更好地理解和应用负载均衡技术。
|
3天前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
3天前
|
XML 缓存 Java
手写Spring源码(简化版)
Spring包下的类、手写@ComponentScan注解、@Component注解、@Autowired注解、@Scope注解、手写BeanDefinition、BeanNameAware、InitializingBean、BeanPostProcessor 、手写AnnotationConfigApplicationContext
手写Spring源码(简化版)
|
3天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
6天前
|
XML 监控 Java
Spring Cloud全解析:熔断之Hystrix简介
Hystrix 是由 Netflix 开源的延迟和容错库,用于提高分布式系统的弹性。它通过断路器模式、资源隔离、服务降级及限流等机制防止服务雪崩。Hystrix 基于命令模式,通过 `HystrixCommand` 封装对外部依赖的调用逻辑。断路器能在依赖服务故障时快速返回备选响应,避免长时间等待。此外,Hystrix 还提供了监控功能,能够实时监控运行指标和配置变化。依赖管理方面,可通过 `@EnableHystrix` 启用 Hystrix 支持,并配置全局或局部的降级策略。结合 Feign 可实现客户端的服务降级。
51 23
|
17天前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
15 0
Spring高手之路22——AOP切面类的封装与解析
|
19天前
|
消息中间件 Java RocketMQ
微服务架构师的福音:深度解析Spring Cloud RocketMQ,打造高可靠消息驱动系统的不二之选!
【8月更文挑战第29天】Spring Cloud RocketMQ结合了Spring Cloud生态与RocketMQ消息中间件的优势,简化了RocketMQ在微服务中的集成,使开发者能更专注业务逻辑。通过配置依赖和连接信息,可轻松搭建消息生产和消费流程,支持消息过滤、转换及分布式事务等功能,确保微服务间解耦的同时,提升了系统的稳定性和效率。掌握其应用,有助于构建复杂分布式系统。
33 0
|
18天前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
1月前
|
存储 NoSQL Redis
redis 6源码解析之 object
redis 6源码解析之 object
53 6
|
3天前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
什么是线程池?从底层源码入手,深度解析线程池的工作原理

推荐镜像

更多