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注解的原理)
-
AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata 用来获取某个 bean 上加了 @Value @Autowired 的成员变量,方法参数的信息,表示为 InjectionMetadata
-
InjectionMetadata 可以完成依赖注入
-
InjectionMetadata 内部根据成员变量,方法参数封装为 DependencyDescriptor 对象
-
有了 DependencyDescriptor,就可以利用 beanFactory.doResolveDependency 方法进行基于类型的查找,然后通过反射来注入方法
2.CommonAnnotationBeanPostProcessor 解析
- @Resource
- @PostConstruct
- @PreDestroy
3.ConfigurationPropertiesBindingPostProcessor 解析
- @ConfigurationProperties
4.ContextAnnotationAutowireCandidateResolver
- 负责获取 @Value 的值
- 解析 @Qualifier、泛型
- @Lazy 等
5.ConfigurationClassPostProcessor 可以解析
-
@ComponentScan
-
@Bean
-
@Import
-
@ImportResource
(@ComponentScan注解原理)
-
首先找到所有带@ComponentScan注解的类,获取该包下的所有文件资源
-
Spring 操作元数据的工具类 CachingMetadataReaderFactory来解析资源类(解析元数据是基于 ASM 技术)
-
通过注解元数据(AnnotationMetadata)获取直接或间接标注的注解信。就是看该包是否加上了@component注解。
-
通过类元数据(ClassMetadata)获取类名,AnnotationBeanNameGenerator 生成 bean 名
-
类名称和bean名称都有了就可以生成bean了
(@Bean注解原理)
-
找到一个类下面所有的带有@Bean注解的方法(通过 CachingMetadataReaderFactory)
-
解析注解上指定的一些方法,如初始化等等
-
通过BeanDefinitionBuilder以工厂形式来创建bd(BeanDefinition)
-
交由DefaultListableBeanFactory来注册bd生成Bean;
(@MapperScan注解原理)
- 扫描@MapperScan所配置的包名,解析包路径下所有接口
- 采用BeanDefinitionBuilder以工厂形式(MapperFactroyBean)来生成BeanDefinition
- 根据获取到的接口名来生成Bean的名字
-
交由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接口呢?
-
内置的注入和初始化不受扩展功能的影响,总会被执行
-
而扩展功能受某些情况影响可能会失效
-
因此 Spring 框架内部的类常用内置注入和初始化
下面来举例一种拓展失效的案例
解决方法:
用内置依赖注入和初始化取代扩展依赖注入和初始化
用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建