Beanfactory和applicationContext(学一下spring了)

1.目录

 2.到底什么是 BeanFactory

3.BeanFactory 能干点啥

4.ApplicationContext 比 BeanFactory 多点啥


 2.到底什么是 BeanFactory

  • 它是 ApplicationContext 的父接口

  • 它才是 Spring 的核心容器, 主要的 ApplicationContext 实现都【组合】了它的功能,【组合】是指 ApplicationContext 的一个重要成员变量就是 BeanFactory

  • 下面附上一张类图

3.BeanFactory 能干点啥

  • 它的成员变量 singletonObjects,内部包含了所有的单例 bean

  • 实际上控制反转、基本的依赖注入、直至 Bean 的生命周期的各种功能,都由它的实现类提供

  • 表面上只有 getBean 

什么是singletonObjects呢?它一般被称位单例池。这里就不得不说一下有关于spring处理循环依赖的方法了:

        spring处理 循环依赖主要是依靠三级缓存来实现:

  1. 一级缓存singletonObjects:单例池,用来缓存已经经过完整生命周期的bean。
  2. 二级缓存earlysingletonObjects ,用来缓存没有经历完整生命周期的bean。
  3. 三级缓存singtonFactory,用来缓存生成对象的factory。

spring在实例化bean'后需要进行依赖注入,如果需要被注入的bean不存在,就会去创建。比如:

  1. spring容器实例化了一个A对象,A对象需要注入B对象,
  2. 首先会查询缓存(看是否存在B对象),没有的话--->spring就会创建B对象,
  3. B对象却需要注入A对象,倘若只用1级缓存,由于A对象没有经历完整的生命周期,其不存在于一级缓存中,则会进入循环,再次创建A对象,又需要注入B.。

 若采用2级缓存就可以解决普通对象的创建循环依赖问题,二级缓存中存在A对象,故B对象在创建时能够注入A对象,不会产生循环依赖。

3级缓存就涉及到了有关代理对象的循环引用问题。大家可以自行查阅资料。

4.ApplicationContext 比 BeanFactory 多点啥

  • ApplicationContext 组合并扩展了 BeanFactory 的功能

  • 国际化、通配符方式获取一组 Resource 资源、整合 Environment 环境、事件发布与监听

国际化主要通过MessageSource来进行语言的转换。

5.@Value注解实现

  1. ContextAnnotationAutowireCandidateResolver 作用之一,获取 @Value 的值

  2. 了解 ${ } 对应的解析器

  3. 了解 #{ } 对应的解析器

TypeConvert 的一项

private static void test3(AnnotationConfigApplicationContext context, ContextAnnotationAutowireCandidateResolver resolver, Field field) {
        DependencyDescriptor dd1 = new DependencyDescriptor(field, false);
        // 获取 @Value 的内容
        String value = resolver.getSuggestedValue(dd1).toString();
        System.out.println(value);

        // 解析 ${}
        value = context.getEnvironment().resolvePlaceholders(value);
        System.out.println(value);
        System.out.println(value.getClass());

        // 解析 #{} @bean3
        Object bean3 = context.getBeanFactory().getBeanExpressionResolver().evaluate(value, new BeanExpressionContext(context.getBeanFactory(), null));

        // 类型转换
        Object result = context.getBeanFactory().getTypeConverter().convertIfNecessary(bean3, dd1.getDependencyType());
        System.out.println(result);
    }

6.@Autoware原理

  1. @Autowired 本质上是根据成员变量或方法参数的类型进行装配

  2. 如果待装配类型是 Optional,需要根据 Optional 泛型找到 bean,再封装为 Optional 对象装配

  3. 如果待装配的类型是 ObjectFactory,需要根据 ObjectFactory 泛型创建 ObjectFactory 对象装配

    • 此方法可以延迟 bean 的获取

  4. 如果待装配的成员变量或方法参数上用 @Lazy 标注,会创建代理对象装配

    • 此方法可以延迟真实 bean 的获取

    • 被装配的代理不作为 bean

  5. 如果待装配类型是数组,需要获取数组元素类型,根据此类型找到多个 bean 进行装配

  6. 如果待装配类型是 Collection 或其子接口,需要获取 Collection 泛型,根据此类型找到多个 bean

  7. 如果待装配类型是 ApplicationContext 等特殊类型

    • 会在 BeanFactory 的 resolvableDependencies 成员按类型查找装配

    • resolvableDependencies 是 map 集合,key 是特殊类型,value 是其对应对象

    • 不能直接根据 key 进行查找,而是用 isAssignableFrom 逐一尝试右边类型是否可以被赋值给左边的 key 类型

  8. 如果待装配类型有泛型参数

    • 需要利用 ContextAnnotationAutowireCandidateResolver 按泛型参数类型筛选

  9. 如果待装配类型有 @Qualifier

    • 需要利用 ContextAnnotationAutowireCandidateResolver 按注解提供的 bean 名称筛选

  10. 有 @Primary 标注的 @Component 或 @Bean 的处理

  11. 与成员变量名或方法参数名同名 bean 的处理

 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A47_1.class);
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 1. 根据成员变量的类型注入
        DependencyDescriptor dd1 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean2"), false);
        System.out.println(beanFactory.doResolveDependency(dd1, "bean1", null, null));
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 2. 根据参数的类型注入
        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), false);
        System.out.println(beanFactory.doResolveDependency(dd2, "bean1", null, null));
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 3. 结果包装为 Optional<Bean2>
        DependencyDescriptor dd3 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean3"), false);
        if (dd3.getDependencyType() == Optional.class) {
            dd3.increaseNestingLevel();
            Object result = beanFactory.doResolveDependency(dd3, "bean1", null, null);
            System.out.println(Optional.ofNullable(result));
        }
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 4. 结果包装为 ObjectProvider,ObjectFactory
        DependencyDescriptor dd4 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean4"), false);
        if (dd4.getDependencyType() == ObjectFactory.class) {
            dd4.increaseNestingLevel();
            ObjectFactory objectFactory = new ObjectFactory() {
                @Override
                public Object getObject() throws BeansException {
                    return beanFactory.doResolveDependency(dd4, "bean1", null, null);
                }
            };
            System.out.println(objectFactory.getObject());
        }
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        // 5. 对 @Lazy 的处理
        DependencyDescriptor dd5 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean2"), false);
        ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();
        resolver.setBeanFactory(beanFactory);
        Object proxy = resolver.getLazyResolutionProxyIfNecessary(dd5, "bean1");
        System.out.println(proxy);
        System.out.println(proxy.getClass());
}
static class Bean1 {
        @Autowired @Lazy private Bean2 bean2;
        @Autowired public void setBean2(Bean2 bean2) {
            this.bean2 = bean2;
        }
        @Autowired private Optional<Bean2> bean3;
        @Autowired private ObjectFactory<Bean2> bean4;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值