通过 applicationcontext 获取value_面试题:BeanFactory和ApplicationContext的区别

BeanFactory和ApplicationContext的区别

面试官:你知道 BeanFactory和ApplicationContext到底有什么区别吗? 面试者: 1、BeanFactory: 是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和获取对象的功能;
// 仅保留重接口,删除了一些重载接口public interface BeanFactory {  String FACTORY_BEAN_PREFIX = "&";    Object getBean(String name) throws BeansException;  ObjectProvidergetBeanProvider(Class requiredType);  boolean isSingleton(String name) throws NoSuchBeanDefinitionException;  boolean isPrototype(String name) throws NoSuchBeanDefinitionException;  boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;  @Nullable  Class> getType(String name) throws NoSuchBeanDefinitionException;}
2、 ApplicationContext: 应用上下文,继承BeanFactory接口,它是Spring的一个功能丰富的容器,提供了更 多的有用的功能; 1) 国际化(MessageSource) 2) 访问资源,如URL和文件(ResourceLoader) 3) 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层   4) 消息发送、响应机制(ApplicationEventPublisher)

95aba2c0949a5e7e8c2c758310bb689c.png

面试官微微一笑:那你知道在Spring环境中,如果采用@Autowired的方式对BeanFactory和ApplicationContext进行赋值,结果是true还是flase?这里我用代码解释一下问题,创建一个 ApplicaitonContextEqulesBeanFactory 类实现 ApplicationContextAware 接口
@Componentpublic class ApplicaitonContextEqulesBeanFactory implements ApplicationContextAware {    private ApplicationContext applicationContextAware;    @Autowired    private ApplicationContext applicationContext;    @Autowired    private BeanFactory beanFactory;    public ApplicationContext getApplicationContextAware() {        return applicationContextAware;    }    public ApplicationContext getApplicationContext() {        return applicationContext;    }    public BeanFactory getBeanFactory() {        return beanFactory;    }    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        this.applicationContextAware = applicationContext;    }}
创建测试类
public class Test {    public static void main(String[] args) {        AnnotationConfigApplicationContext annotationConfigApplicationContext =                new AnnotationConfigApplicationContext(AppConfig.class);        ApplicaitonContextEqulesBeanFactory applicaitonContextEqulesBeanFactory= (ApplicaitonContextEqulesBeanFactory) annotationConfigApplicationContext.getBean("applicaitonContextEqulesBeanFactory");        // BeanFactory == AnnotationConfigApplicationContext        System.out.println(applicaitonContextEqulesBeanFactory.getBeanFactory()== annotationConfigApplicationContext);        // AnnotationConfigApplicationContext == ApplicaitonContext        System.out.println(annotationConfigApplicationContext == applicaitonContextEqulesBeanFactory.getApplicationContext());        // ApplicaitonContext == ApplicaitonContextaware        System.out.println(applicaitonContextEqulesBeanFactory.getApplicationContext()==                applicaitonContextEqulesBeanFactory.getApplicationContextAware());        // BeanFactory == ApplicaitonContext        System.out.println(applicaitonContextEqulesBeanFactory.getBeanFactory()==                applicaitonContextEqulesBeanFactory.getApplicationContext());        // BeanFactory == AnnotationConfigApplicationContext.getBeanFactory        System.out.println(applicaitonContextEqulesBeanFactory.getBeanFactory()==                annotationConfigApplicationContext.getBeanFactory());        // BeanFactory == ApplicationContext.getBeanFactory        System.out.println(applicaitonContextEqulesBeanFactory.getBeanFactory()==                applicaitonContextEqulesBeanFactory.getApplicationContext().getAutowireCapableBeanFactory());        // 通过查找的方式获取 BeanFactory        //BeanFactory beanFactory=annotationConfigApplicationContext.getBean(BeanFactory.class);            }}

我们来看运行结果:

a3b8c4a531e5759992e6db236c9b789b.png

看到第一个结果false 对应的是 BeanFactory == AnnotationConfigAppli cationContext,这个 BeanFactory 是通过 @Autowired赋值,我们再来看第二个 AnnotationConfigApplicationContext == ApplicaitonContext,这里结果为true,第三个 ApplicaitonContext == ApplicaitonContextaware也为true,第四个 BeanFactory == ApplicaitonContext为false,第五个 AnnotationConfigApplicationContext.getBeanFactory == BeanFactory 为true。最后一个 ApplicationContext.getBeanFactory == BeanFactory 为true,我们可以得出结论, AnnotationConfigAppli cationContext就是我们的ApplicaitionContext的来源,而且实现了 ApplicationContextAware 的数据来源也是 AnnotationConfigAppli cationContext,注意关键点来了BeanFactory不等于ApplicationContext,而是等于ApplicationContext.getAutowireCapableBeanFactory,这是为什么呢?我们看看ApplicationContext.getAutowireCapableBeanFactory方法

990e57733b6857479e52798f97ec5522.png

可以看到这里我们同时验证了ApplicationContext对象==AnnotationConfigApplicationContext ,在上个Spring环境的章节,笔者提到,BeanFactory只是Spring环境的一部分,而这个BeanFactory在一开始就在Spring内部创建了,所以我们这里的this.BeanFactory是内建的,因此回到我们的主题BeanFactory和ApplicationContext的区别,ApplicationContext虽然继承了BeanFactory,通过上面测试的结果就可以发现它们两者并不相同,而在ApplicationContext的子实现中有一个内部的BeanFactory属性,所以在ApplicationContext对工厂操作的真正角色就是这个BeanFactory,那么为什么我们注入BeanFactory和ApplicationContext他们的数据源不一样呢?这里我们先看一段代码

public class Test {    public static void main(String[] args) {      AnnotationConfigApplicationContext annotationConfigApplicationContext=          new AnnotationConfigApplicationContext(AppConfig.class);      ApplicaitonContextEqulesBeanFactory applicaitonContextEqulesBeanFactory =          (ApplicaitonContextEqulesBeanFactory) annotationConfigApplicationContext.getBean("applicaitonContextEqulesBeanFactory");      // BeanFactory == AnnotationConfigApplicationContext      System.out.println(applicaitonContextEqulesBeanFactory.getBeanFactory()==          annotationConfigApplicationContext);      // AnnotationConfigApplicationContext == ApplicaitonContext      System.out.println(annotationConfigApplicationContext ==          applicaitonContextEqulesBeanFactory.getApplicationContext());      // ApplicaitonContext == ApplicaitonContextaware      System.out.println(applicaitonContextEqulesBeanFactory.getApplicationContext()==          applicaitonContextEqulesBeanFactory.getApplicationContextAware());            // BeanFactory == ApplicaitonContext      System.out.println(applicaitonContextEqulesBeanFactory.getBeanFactory()==          applicaitonContextEqulesBeanFactory.getApplicationContext());      // BeanFactory == AnnotationConfigApplicationContext.getBeanFactory      System.out.println(applicaitonContextEqulesBeanFactory.getBeanFactory()==          annotationConfigApplicationContext.getBeanFactory());      // BeanFactory == ApplicationContext.getBeanFactory      System.out.println(applicaitonContextEqulesBeanFactory.getBeanFactory()==          applicaitonContextEqulesBeanFactory.getApplicationContext().getAutowireCapableBeanFactory());      // 通过查找的方式获取 BeanFactory      BeanFactory beanFactory=annotationConfigApplicationContext.getBean(BeanFactory.class);    }}

最后一行我们添加了  BeanFactory beanFactory=annotationConfigApplicationContext.getBean(BeanFactory.class);我们先看执行结果

9ddcc6c8aa4375c38e6f8add8fa3279e.png

看到这里出现了异常,为什么会出现异常?通常来说我们依赖注入的数据来源都是工厂获取,而我们通过getBean的方式也是从工厂得到的,依赖注入的数据来源和依赖查找的方式是来自于不同的数据源,这不能说完全不同的数据源,只是Spring对一些关键类提供了特殊的额外空间来给予依赖注入,那么这里的注入来源来自哪里呢?看下图:

015bc7cdd4eee4e5f07f00ce38394fb0.png

仔细看这几个value值就可以得出结论为什么注入的BeanFactory和Appllication不同了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值