面试管:你知道BeanFactory和ApplicationContext的区别吗?

​BeanFactory和ApplicationContext的区别

 

面试官:你知道BeanFactory和ApplicationContext到底有什么区别吗?

面试者:

1、BeanFactory:是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和获取对象的功能;

// 仅保留重接口,删除了一些重载接口
public interface BeanFactory {
​
  String FACTORY_BEAN_PREFIX = "&";
  
  Object getBean(String name) throws BeansException;
​
  <T> ObjectProvider<T> getBeanProvider(Class<T> 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)

面试官微微一笑:那你知道在Spring环境中,如果采用@Autowired的方式对BeanFactory和ApplicationContext进行赋值,结果是true还是flase?这里我用代码解释一下问题,创建一个ApplicaitonContextEqulesBeanFactory 类实现ApplicationContextAware 接口

@Component
public 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);
        
    }
}

我们来看运行结果:

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

可以看到这里我们同时验证了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);我们先看执行结果

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

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值