DefaultListableBeanFactory和ApplicationContext

DefaultListableBeanFactory:

        DefaultListableBeanFactory是 BeanFactory 最重要的实现,像控制反转依赖注入功能,都是它来实现。

1.beanFactory 可以通过 registerBeanDefinition 注册一个 bean definition 对象

  • 我们平时使用的配置类、xml、组件扫描等方式都是生成 bean definition 对象注册到         beanFactory 当中
  •  bean definition 描述了这个 bean 的创建蓝图:scope 是什么、用构造还是工厂创建、初始化销毁方法是什么,等等

2.beanFactory 需要手动调用 beanFactory 后处理器对它做增强

  • 例如通过解析 @Bean、@ComponentScan 等注解,来补充一些 bean definition

  • beanFactory 需要手动添加 bean 后处理器,以便对后续 bean 的创建过程提供增强

    • 例如 @Autowired,@Resource 等注解的解析都是 bean 后处理器完成的

    • bean 后处理的添加顺序会对解析结果有影响,见视频中同时加 @Autowired,@Resource 的例子

3.beanFactory 需要手动调用方法来初始化单例

4.beanFactory 需要额外设置才能解析 ${} 与 #{}

既然提到了,就来说一下后处理器吧:

1.AutowiredAnnotationBeanPostProcessor 解析 @Autowired 与 @Value,(也就是

@Autoware注解和@Value注解的原理)

  1. AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata 用来获取某个 bean 上加了 @Value @Autowired 的成员变量,方法参数的信息,表示为 InjectionMetadata

  2. InjectionMetadata 可以完成依赖注入

  3. InjectionMetadata 内部根据成员变量,方法参数封装为 DependencyDescriptor 对象

  4. 有了 DependencyDescriptor,就可以利用 beanFactory.doResolveDependency 方法进行基于类型的查找,然后通过反射来注入方法

2.CommonAnnotationBeanPostProcessor 解析

  • @Resource
  • @PostConstruct
  • @PreDestroy

3.ConfigurationPropertiesBindingPostProcessor 解析

  • @ConfigurationProperties

4.ContextAnnotationAutowireCandidateResolver

  • 负责获取 @Value 的值
  • 解析 @Qualifier、泛型
  • @Lazy 等

5.ConfigurationClassPostProcessor 可以解析

  • @ComponentScan

  • @Bean

  • @Import

  • @ImportResource   

(@ComponentScan注解原理)

  1. 首先找到所有带@ComponentScan注解的类,获取该包下的所有文件资源

  2. Spring 操作元数据的工具类 CachingMetadataReaderFactory来解析资源类(解析元数据是基于 ASM 技术)

  3. 通过注解元数据(AnnotationMetadata)获取直接或间接标注的注解信。就是看该包是否加上了@component注解。

  4. 通过类元数据(ClassMetadata)获取类名,AnnotationBeanNameGenerator 生成 bean 名

  5. 类名称和bean名称都有了就可以生成bean了 


(@Bean注解原理)

  1.  找到一个类下面所有的带有@Bean注解的方法(通过 CachingMetadataReaderFactory)

  2. 解析注解上指定的一些方法,如初始化等等

  3. 通过BeanDefinitionBuilder以工厂形式来创建bd(BeanDefinition)

  4. 交由DefaultListableBeanFactory来注册bd生成Bean;


 

(@MapperScan注解原理)

  1. 扫描@MapperScan所配置的包名,解析包路径下所有接口
  2. 采用BeanDefinitionBuilder以工厂形式(MapperFactroyBean)来生成BeanDefinition
  3. 根据获取到的接口名来生成Bean的名字
  4. 交由DefaultListableBeanFactory来注册bd生成Bean;

(带有@Mapper注解就会自动装配动态代理可以不用写xml文件)


 

ApplicationContext:

  • ClassPathXmlApplicationContext,从类路径查找 XML 配置文件,创建容器(旧)

  • FileSystemXmlApplicationContext,从磁盘路径查找 XML 配置文件,创建容器(旧)

这2个都是基于xml的方式来配置bean,其本质上也是基于BeanFactory来创建beanfactory的,通过XmlBeanDefinitionReader.loadBeanDefinitions来加载xml的配置初始化工厂。

  • AnnotationConfigApplicationContext,Spring中非 web 环境容器(新)

这个是我们比较 熟悉的基于注解开发的ApplicationContext,他就帮我们做了很多的处理(比起上面的DefaultListableBeanFactory),我们不需要再手动添加后处理器和初始化单例等等。简便。

  •  AnnotationConfigServletWebServerApplicationContext,Spring boot 中 servlet web 环境容器(新)

这里是一个简单的web配置 

Aware 接口及 InitializingBean 接口:

Aware 接口提供了一种【内置】 的注入手段,例如

  • BeanNameAware 接口 注入 bean 的名字

  • BeanFactoryAware 接口 注入 BeanFactory 容器

  • ApplicationContextAware 接口 注入 ApplicationContext 容器

  • EmbeddedValueResolverAware 接口 注入 ${} 解析器

InitializingBean 接口提供了一种【内置】的初始化手段

其实这些功能都可以用后处理器来实现,为什么又要用Aware接口呢?

  1. 内置的注入和初始化不受扩展功能的影响,总会被执行

  2. 而扩展功能受某些情况影响可能会失效

  3. 因此 Spring 框架内部的类常用内置注入和初始化

下面来举例一种拓展失效的案例

解决方法:

  • 用内置依赖注入和初始化取代扩展依赖注入和初始化

  • 用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值