Spring之旅-----BeanFactory与Application到底是啥?

前言


你我在此相遇,全因八股文。

一年之后就要找实习了,所以我想提前储备好知识,希望被面试的时候不会被拷打死。本系列文章将会分享我探索Spring框架的经历与了解到的知识。

至此,既然逃不掉,那就使劲造。

以下是本文探讨的问题:

  • BeanFactory与Application的区别?
  • BeanFactory与Application的实现?

一.BeanFactory与ApplicationContext的区别?

1.它俩为何物?

BeanFactory顾名思义,Bean的加工厂,主要责任是对Bean进行实例化配置管理,并支持延迟初始化(支持在获取Bean时才进行实例化),提供了最简单的容器功能。

ApplicationContext-------应用上下文 ,是BeanFactory的子接口,由BeanFactory派生而来,是一个维护Bean定义以及对象之间协作关系的高级接口,能提供更多企业级功能。

两者同为Spring框架中的容器,而ApplicationContext继承了多个接口,相比BeanFactory拓展了更多实用功能,作为Spring核心容器的它起着不可获缺的功能。

我们先看到两者的继承关系

 

ApplicatonContext间接继承了BeanFactory

同时BeanFactory作为一个简单功能的容器,体现有二。

其一,我们可以在SpringApplication.run方法生成

ConfigurableApplicationContext的一个实现类中AbstractApplicationContext的getBean方法得知其

底层是获取BeanFactory对象调用其中getBean方法的。

其二,DefaultListableBeanFactorys实现了BeanFactory,作为ApplicationContext属性的同时 ,设置了一个类型为ConcurrentHashMap的属性来保存所有单例Bean

遍历结果

 

2.区别

BeanFactory作为古老的Factory提供了IOC(控制反转:将对象控制权的转移,从程序代码本身反转到了外部容器。 把对象的创建、初始化、销毁等工作交给容器来做。)和DI(依赖注入)功能,但是却无法支持spring插件,例如:AOP、Web应用等功能。

当我们使用BeanFactory去获取Bean的时候,我们只是实例化了该容器,而该容器中的bean并没有被实例化。当我们getBean的时候,才会实时实例化该bean对象,俗称懒加载

BeanFactory接口的一些常见实现类包括DefaultListableBeanFactoryXmlBeanFactory

除了提供BeanFactory的所有功能,ApplicationContext还提供了更多的企业级特性,如AOP(面向切面编程)、事件发布、国际化、资源加载、Bean生命周期管理、安全性等 

  1. EnvironmentCapable   整合了Environment的环境  
  2. MessageSource   国际化
  3. ResourcePatternResolver   通过通配符获取一组Resource的资源
  4. ApplicationEventPublisher  事件发布与监听 

 

 

 事件发布与监听 

 

 

当我们使用ApplicationContext去获取bean的时候,是会预先创建好所需要的bean的

 

二.BeanFactory与ApplicationContext的实现?

BeanFactory的实现

创建BeanFactory对象——>做bean的定义(class,scope,初始化,销毁)——>注册bean

——>为BeanFactory添加常用处理器以及设置比较器(用来解析注解,比如@Bean,@Configuration)——>使后处理器工作——>补充后处理器

注:第一个添加常用处理器只是把一些后处理器加入到了BeanFactory,只是存在于BeanFactory中的一个bean而已,还没建立联系,第二个是加上BeanFactory和后处理器的联系,才能告诉BeanFactory每个bean创建后,需要哪些后处理器。

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

//定义
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).
        setScope("singleton").getBeanDefinition();

//注册
beanFactory.registerBeanDefinition("config",beanDefinition);

//为BeanFactory提供一些常用处理器
//此外还设置了比较器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

//根据一个类型获取多个Bean,使其工作,扩展
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(beanFactoryPostProcessor -> {
    System.out.println(beanFactoryPostProcessor);
    beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<");


//Bean后处理器,对bean生命周期各个阶段提供扩展,告诉bean工厂,创建bean实例的时候需要哪些后处理器
//internalCommonAnnotationProcessor  Resource处理器
beanFactory.getBeansOfType(BeanPostProcessor.class).
        values().stream().sorted(beanFactory.getDependencyComparator())
        .forEach(beanPostProcessor -> {
            System.out.println("beanFactory.getBeansOfType数据如下:"+beanPostProcessor);
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        });

for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
}
//预先创建好Bean,Bean的创建是懒加载
beanFactory.preInstantiateSingletons();

 

后处理器实现

@Autowried是根据类型进行自动装配的,当一个接口有两个实现类并且他们都注入到容器中的时候,假设此时用@Autowried为此接口进行依赖注入的话会发生什么?

答案是报异常

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException

因为BeanFactory不知道为此接口注入哪个实现类。解决方法用@Qualifier或者改接口变量名,将其改为和对应实现类名一致也可以注入成功。

@Resource中默认也是根据变量名,但是加了name的话,name的优先级会更高些

假设此时为一个类中的属性进行依赖注入,同时添加@Resource@Autowried又会发生什么?

答案是注入成功

因为在它们有着优先级的关系,而@Autowried比@Resource优先级高些,所以会直接处理@Autowried而忽略@Resource。过程中添加一些处理器的时候,便设置了比较器,通过阅读源码得知,它们以设置的数值大小来进行比较。

 

这是@Resource的处理器,里面的setOrder的参数表示了他的数值大小,在之后决定了它的优先级。

ApplicationContext的实现

Spring提供了多种类型的容器实现,供我们在不同的应用场景选择——

  • ClassPathXmlApplicationContext(从类路径加载XML配置文件)
  • AnnotationConfigApplicationContext(使用Java注解配置)
  • FileSystemXmlApplicationContext(从文件系统加载XML配置文件)
  • XmlWebApplicationContext(从web应用下的一个或多个xml配置文件加载上下文定义,适用于xml配置方式)

同时相比BeanFactory省去了后处理器添加补充的操作

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值