• 【Spring】IoC容器


    前言

    上一篇文章已经学习了【IoC的主要实现策略】有2种:
    1、依赖查找
    2、依赖注入
    这里稍加详细的介绍一下依赖查找

    1.依赖查找的方式

    依赖查找的方式可以以多种维度来划分:
    1.按名称/类型/注解查找
    2.按单一类型/集合类型/层次性依赖查找
    3.延迟查找、实时查找

    1.1维度一

    1.1.1根据 Bean 名称查找

    实时
        private static void lookupInRealTime(BeanFactory beanFactory) {
            User user = (User) beanFactory.getBean("user");
            System.out.println("实时查找:" + user);
        }
    
    延迟
        private static void lookupInLazy(BeanFactory beanFactory) {
            ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
            User user = objectFactory.getObject();
            System.out.println("延迟查找:" + user);
        }
    
    这里省略了一个名为user的bean
        <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
            <property name="targetBeanName" value="user"/>
        </bean>
    

    1.1.2根据 Bean 类型查找

        private static void lookupByType(BeanFactory beanFactory) {
            User user = beanFactory.getBean(User.class);
            System.out.println("实时查找:" + user);
        }
    

    1.1.3根据 Java注解查找

        private static void lookupByAnnotationType(BeanFactory beanFactory) {
            if (beanFactory instanceof ListableBeanFactory) {
                ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
                Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
                System.out.println("查找标注 @Super 所有的 User 集合对象:" + users);
            }
        }
    

    1.2维度二

    1.2.1单一类型查找

    单一类型的查找是基于BeanFactory这个接口来实现的。

    • 根据Bean名称查找
      • getBean(String)
    • 根据Bean类型查找
      • Bean实时查找
        • getBean(Class)
      • Bean延迟查找 (Spring5.1)
        • getBeanProvider(Class)
        • getBeanProvider(ResolvableType)
    • 根据Bean名称+类型查找
      • getBean(String, Class)

    1.2.2集合类型查找

    集合类型的查找是基于ListableBeanFactory这个接口来实现的。

    • 根据Bean类型查找
      • 获取同类型Bean名称列表
        • getBeanNamesForType(Class)
        • getBeanNamesForType(ResolvableType) [Spring4.2]
      • 获取同类型Bean实例列表
        • getBeansOfType(Class)以及它的重载方法
    • 根据注解类型查找
      • Spring3.0获取标注类型Bean名称列表
        • getBeanNamesForAnnotation(Class<? extends Annotation>)
      • Spring3.0获取标注类型Bean实例列表
        • getBeansWithAnnotation(Class<? extends Annotation>)
      • Spring3.0获取指定名称 + 标注类型Bean实例
        • findAnnotationOnBean(String, Class<? extends Annotation>)

    1.2.3层次性查找

    层次性类型的查找是基于HierarchicalBeanFactory这个接口来实现的。

    这里的层次性查找是有一点类似于类加载的双亲委派,但是它的实现是需要依赖于下面接口的方法:

    public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
    	/**
    	 * Set the parent of this bean factory.
    	 * <p>Note that the parent cannot be changed: It should only be set outside
    	 * a constructor if it isn't available at the time of factory instantiation.
    	 * @param parentBeanFactory the parent BeanFactory
    	 * @throws IllegalStateException if this factory is already associated with
    	 * a parent BeanFactory
    	 * @see #getParentBeanFactory()
    	 */
    	void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
    

    实现的基本逻辑就是:
    1.获取到子BeanFactory
    2.创建一个ParentBeanFactory
    3.设置父子关系
    4.获取bean的时候,先判断其ParentBeanFactory是否存在,不存在,则判断子BeanFactory是否存在。使用递归。

    这里我不是很清楚层次性依赖查找有什么用处,目前的项目业务中一般只会有默认的Spring创建的BeanFactory。

    1.3维度三

    1.3.1延迟查找

    延迟查找可以用过2个接口实现:
    1、ObjectFactory
    2、ObjectProvider

    其中ObjectProvider继承了ObjectFactory:

    public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
    

    这里的延迟查找:
    基本原理就是
    1.通过AbstractApplicationContext接口的方法:getBeanProvider(Class<T> requiredType)获取到一个ObjectFactory或ObjectProvider的实例
    2.当真正需要使用指定类型【上一步的requiredType】的实例的时候,调用ObjectFactory实例【上一步的返回值】的T getObject(),在第二步才是真正的执行依赖查找。

    示例

        private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
            ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class); //第一步
            System.out.println(objectProvider.getObject());  //第二步,这一步跟进源码,可以知道这一步是怎么实际查找的。
            //DependencyObjectProvider.java
        }
    
    

    非延迟初始化Bean也能实现延迟查找:
    也就是说 即时初始化的bean也能实现延迟查找。

    实际的ObjectProvider实现类一般是在DefaultListableBeanFactory.java中的内部类DependencyObjectProvider.java:

    1.3.2实时查找

    除了延迟查找,基本都是实时查找,没什么好说的。

    2.依赖查找的安全性

    3.Spring内建依赖

    Spring默认容器启动的时候,有一些内置的依赖,这些依赖是帮助spring实现某些基础功能所需的。算是Spring给自身的扩展和增强。


    4.依赖查找的经典异常

  • 相关阅读:
    【Selenium04篇】python+selenium实现Web自动化:文件上传,Cookie操作,调用 JavaScript,窗口截图
    【Selenium03篇】python+selenium实现Web自动化:元素三类等待,多窗口切换,警告框处理,下拉框选择
    【Selenium02篇】python+selenium实现Web自动化:鼠标操作和键盘操作!
    【Selenium01篇】python+selenium实现Web自动化:搭建环境,Selenium原理,定位元素以及浏览器常规操作!
    面试官看到一定会打我---软件测试工程师面试套路和暗语灵魂解密
    十年测试老鸟告诉你--自动化测试选JAVA还是选Python--写给还在迷茫中的朋友
    华为十年测试老鸟教您如何便写高质量的自动化测试工程师简历--看完必有所获
    工作中常用的Android系统ADB命令收集
    自动化测试中的三类等待深入剥析
    JAVA自动化之Junit单元测试框架详解
  • 原文地址:https://www.cnblogs.com/1626ace/p/15104609.html
Copyright © 2020-2023  润新知