Spring编程思想:二. Spring IoC依赖查找

1. 单一类型依赖查找

单一类型依赖查找接口:BeanFactory

  • 根据Bean名称查找:
    • getBean(String)
  • 根据Bean类型查找:
    • Bean实时查找:
      • getBean(Class)
    • Spring 5.1 Bean延迟查找:
      • getBeanProvider(Class)
      • getBeanProvider(ResolvableType)
    • 根据Bean名称 + 类型查找:getBean(String, Class)

2. 集合类型依赖查找

集合类型依赖查找接口:ListableBeanFactory

  • 根据Bean类型查找:
    • 获取同类型Bean名称列表:
      • getBeanNamesForType(Class)
      • getBeanNamesForType(ResolvableType)
    • 获取同类型Bean实例列表
      • getBeansOfTypoe(Class)
  • 通过注解类型查找
    • 获取标注类型Bean名称列表:getBeanNamesForAnnotation(Class<? extends Annotation)
    • 获取标注类型Bean实例列表:getBeansWithAnnotation(Class<? extends Annotation>)

3. 层次性依赖查找

层次性依赖查找接口:HierarchicalBeanFactory

  • 父BeanFactory:getParentBeanFactory()
  • 层次性查找:
    • 根据Bean名称查找:基于 containsLocalBean 方法实现
    • 根据Bean类型查找实例列表:
      • 单一类型:BeanFactoryUtils#beanOfType()
      • 集合类型:BeanFactoryUtils#beansOfTyoeIncludingAncestors()
    • 根据Java注解查找名称列表:BeanFactoryUtils#beanNamesForTypeIncludingAncestors()

image-20201109074359453

从上图中可以看出,ConfigurableBeanFactory 是层次性的依赖查找的BeanFactory,而 ConfigurableListableBeanFactory 既是层次性的也是集合类型的依赖查找。

Spring中常用类的一些继承关系如下:

image-20201114125221546

4. 延迟依赖查找

延迟依赖查找接口:ObjectFactoryObjectProvider

public class ObjectProviderDemo {

    /**
     * 方法名就是Bean的名称
     */
    @Bean
    @Primary                            // 必须加上这个,否则 applicationContext.getBeanProvider(String.class) 会报错
    public String hello() {
        return "hello world";
    }

    @Bean
    public String leihou() {
        return "leihou";
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(ObjectProviderDemo.class);          // 这种情况下@Configuration注解不是必须的
        applicationContext.refresh();

        lookupByObjectProvider(applicationContext);
        lookupIfAvailable(applicationContext);
        lookupByStreamOps(applicationContext);

        applicationContext.close();
    }

    private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<String> beanProvider = applicationContext.getBeanProvider(String.class);
        System.out.println(beanProvider.getObject());
    }

    private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<User> beanProvider = applicationContext.getBeanProvider(User.class);
        User user = beanProvider.getIfAvailable(User::createUser);         // 如果User这个Bean不存在,则使用 User.createUser()
        System.out.println("当前 User 对象:" + user);
    }

    private static void lookupByStreamOps(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<String> beanProvider = applicationContext.getBeanProvider(String.class);
        beanProvider.stream().forEach(System.out::println);
    }
}

5. 安全依赖查找

依赖查找类型代表实现是否安全
单一类型查找BeanFactory#getBean
ObjectFactory#getObject
ObjectProvider#getIfAvailable
集合类型查找ListableBeanFactory#getBeansOfType
ObjectProvider#stream
  • BeanFactory#getBean() 会抛下面的异常

    • NoSuchBeanDefinitionException
    • NoUniqueBeanDefinitionException
  • ObjectFactory#getObject() 会抛 BeansException

6. 内建可查找的依赖

AbstractApplicationContext 内建可查找的依赖:

Bean名称Bean实例使用场景
environmentEnvironment对象外部化配置及Profiles
systemPropertiesjava.util.Properties对象Java系统属性
systemEnvironmentjava.util.Map对象操作系统环境变量
messageSourceMessageSource对象国际化文案
lifecycleProcessorLifecycleProcessor对象Lifecycle Bean处理器
applicationEventMulticasterApplicationEventMulticaster对象Spring事件广播器
internalConfigurationAnnotationProcessorConfigurationClassPostProcessor对象处理Spring配置类
internalAutowiredAnnotationProcessorAutowiredAnnotationBeanPostProcessor对象处理 @Autowired 以及 @Value 注解
internalCommonAnnotationProcessorCommonAnnotationBeanPostProcessor对象(条件激活)处理JSR-250注解,如@PostConstruct
internalEventListenerProcessorEventListenerMethodProcessor对象处理标注@EventListener的Spring事件监听方法
internalEventListenerFactoryDefaultEventListenerFactory对象@EventListener事件监听方法适配为ApplicationListener
internalPersistenceAnnotationProcessorPersistenceAnnotationBeanPostProcessor对象(条件激活)处理JPA注解场景

后面以 internal 开头的几个Bean其实完整的Bean名称是以 org.springframework.xx 开头的。

具体可以查看 AnnotationConfigUtils

image-20201109212616815

7. 依赖查找中的经典异常

异常类型触发条件(举例)场景举例
NoSuchBeanDefinitionException当查找Bean在IoC容器中不存在BeanFactory#getBean()
NoUniqueBeanDefinitionException类型依赖查找时,IoC容器存在多个Bean实例BeanFactory#getBean(Class)
BeanInstantiationException当Bean对应的类型为非具体类时BeanFactory#getBean()
BeanCreationException当 Bean 初始化过程中Bean初始化方法执行异常时
BeanDefinitionStoreException当BeanDefinition配置元信息非法时XML配置资源无法打开时
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值