1、什么是BeanFactory
BeanFactory是一个工厂接口,负责生产和管理bean的一个工厂。ApplicationContext 的父接口,它才是 Spring 的核心容器, 主要的 ApplicationContext 实现都【组合】了它的功能。
2、BeanFactory功能
表面上主要方法只有getBean(),但是它实际上的职责包括:实例化、定位、配置应用程序中的对象以及建立这些对象之间的依赖。BeanFactory是一个工厂接口,Spring给出的具体实现包括DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等。
3、重要实现DefaultListableBeanFactory
DefaultListableBeanFactory是Bean工厂的一个默认实现,我们可以对它进行拓展以便实现自定义的Bean工厂。作为默认的Bean工厂实现。
从上往下开始介绍各个类以及接口的作用:
- AliasRegistry(接口):alias指的是bean的别名,而aliasRegistry定义了对alias的增删改查等操作。
- SimpleAliasRegistry(类):主要使用map作为alias的缓存,并对接口AliasRegistry进行实现。
- SingletonBeanRegistry(接口):定义对单例的注册及获取。
- BeanFactory(接口):定义获取bean及bean的各种属性。
- DefaultSingleTonBeanRegistry(接口):实现了SingletonBeanRegistry的方法,同时继承了SimpleAliasRegistry。
- HierarchicalBeanFactory(接口):继承BeanFactory,也就是在BeanFactory定义功能的基础上增加了对parantFactory的支持。
- BeanDefinitionRegistry(接口):定义对BeanDefinition的增删改查功能,BeanDefinition就是描述一个bean的实例,包含了属性值(scope、bean的name、lazy加载模式等),构造参数以及其他更多的实现信息。
- FactoryBeanRegistrySupport(类):在DefaultSingleTonBeanRegistry基础上增加了对FactoryBean的特殊功能。
- ConfigurableBeanFactory(接口):提供配置Factory的各种方法,包括设置父工厂、bean的加载器、添加BeanPostProcessor等功能。
- ListableBeanFactory(接口):根据各种条件获取bean的配置清单,可以根据bean的name、type等条件获得bean配置清单。
- AbstractBeanFactory(类):综合FactoryBeanRegistrySupport和ConfigurableBeanFactory的功能。
- AutowireCapableBeanFactory(接口):提供创建Bean、自动注入、初始化以及应用bean的后置处理器。
- AbstractAutowireCapableBeanFactory(类):综合AbstractBeanFactory并对接口AutowireCapableBeanFactory进行实现
- ConfigurableListableBeanFactory:BeanFactory配置清单,指定忽略类型及接口等。
- DefaultListableBeanFactory:综合上面所有功能,主要对Bean注册后的处理。
使用DefaultListableBeanFactory来创建一些bean实例:
package com.zp.example02;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import javax.annotation.Resource;
public class TestBeanFactory {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
//创建Bean定义信息
AbstractBeanDefinition beanDefinition= BeanDefinitionBuilder
.genericBeanDefinition(Config.class)
.setScope("singleton")
.getBeanDefinition();
//向bean工厂中添加bean定义信息
beanFactory.registerBeanDefinition("config", beanDefinition);
// 给 BeanFactory 添加一些常用的后置处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// BeanFactory 后置处理器主要功能,补充了一些 bean 定义
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
// Bean 后置处理器, 针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource ...
beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
.sorted(beanFactory.getDependencyComparator())
.forEach(beanPostProcessor -> {
System.out.println(">>>>" + beanPostProcessor);
beanFactory.addBeanPostProcessor(beanPostProcessor);
});
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
beanFactory.preInstantiateSingletons(); // 准备好所有单例
/*
学到了什么:
a. beanFactory 不会做的事
1. 不会主动调用 BeanFactory 后处理器
2. 不会主动添加 Bean 后处理器
3. 不会主动初始化单例
4. 不会解析beanFactory 还不会解析 ${ } 与 #{ }
b. bean 后处理器会有排序的逻辑
*/
//比较CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor的排序优先级
System.out.println("Common:" + (Ordered.LOWEST_PRECEDENCE - 3));
System.out.println("Autowired:" + (Ordered.LOWEST_PRECEDENCE - 2));
}
@Configuration
static class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
@Bean
public Bean3 bean3() {
return new Bean3();
}
@Bean
public Bean4 bean4() {
return new Bean4();
}
}
interface Inter {
}
static class Bean3 implements Inter {
}
static class Bean4 implements Inter {
}
static class Bean1 {
public Bean1() {
System.out.println("构造bean1");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
@Autowired
@Resource(name = "bean4")
private Inter bean3;
public Inter getInter() {
return bean3;
}
}
static class Bean2 {
public Bean2() {
System.out.println("构造bean2");
}
}
}
-
beanFactory 可以通过 registerBeanDefinition 注册一个 bean definition 对象
- 我们平时使用的配置类、xml、组件扫描等方式都是生成 bean definition 对象注册到 beanFactory 当中
- bean definition 描述了这个 bean 的创建蓝图:scope 是什么、用构造还是工厂创建、初始化销毁方法是什么,等等
-
beanFactory 需要手动调用 beanFactory 后处理器对它做增强
- 例如通过解析 @Bean、@ComponentScan 等注解,来补充一些 bean definition
-
beanFactory 需要手动添加 bean 后处理器,以便对后续 bean 的创建过程提供增强
- 例如 @Autowired,@Resource 等注解的解析都是 bean 后处理器完成的
- bean 后处理的添加顺序会对解析结果有影响,见视频中同时加 @Autowired,@Resource 的例子
-
beanFactory 需要手动调用方法来初始化单例
-
beanFactory 需要额外设置才能解析 ${} 与 #{}
4、什么是ApplicationContext
由BeanFactory派生而来,提供了更多面向实际应用的功能,以一种更向面向框架的方式工作以及对上下文进行分层和实现继承。其既派生自BeanFactory也组合使用BeanFactory获取bean,并相对于BeanFactory扩展了一些功能。
我们可以看到ApplicationContext除了继承自BeanFactory接口外,还继承了额外的扩展接口分别是:MessageSource、ResourcePatternResolver、ApplicationEventPublisher、EnviromentCapable这四个接口,这四个接口就是ApplicationContext相对于BeanFactory扩展的额外的功能。
- MessageSource:用于解析消息,并且支持消息参数化和国际化。
- ResourcePatternResolver: 用于资源访问,例如URL和文件。
- ApplicationEventPublisher: 用于时间发布。
- EnviromentCapable: 整合 Environment 环境。
package com.zp.springDemo;
import com.zp.springDemo.example01.UserRegisteredEvent;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@SpringBootApplication
public class SpringDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);
//国际化
System.out.println("\n国际化示例--------------------------------------");
System.out.println(context.getMessage("hi", null, Locale.CHINA));
System.out.println(context.getMessage("hi", null, Locale.ENGLISH));
System.out.println(context.getMessage("hi", null, Locale.JAPANESE));
System.out.println("----------------------------------------------\n");
//资源访问
System.out.println("资源访问示例-------------------------------------");
Resource[] resources = new Resource[0];
try {
resources = context.getResources("classpath*:META-INF/spring.factories");
} catch (IOException e) {
e.printStackTrace();
}
for (Resource resource : resources) {
System.out.println("获取到所有的spring.factories文件为---"+resource);
}
System.out.println("----------------------------------------------\n");
//事件发布
context.publishEvent(new UserRegisteredEvent(context));
//环境参数
System.out.println("获取环境参数示例----------------------------------------");
ConfigurableEnvironment environment = context.getEnvironment();
Map<String, Object> systemEnvironment = environment.getSystemEnvironment();
systemEnvironment.entrySet().forEach(x->
System.out.println("环境参数的KEY为----"+x.getKey()+"----环境参数的value为----"+x.getValue())
);
System.out.println("------------------------------------------------------\n");
}
}
package com.zp.springDemo.example01;
import org.springframework.context.ApplicationEvent;
public class UserRegisteredEvent extends ApplicationEvent {
public UserRegisteredEvent(Object source) {
super(source);
System.out.println("事件发布成功---------\n");
}
}
5、ApplicationContext的一些实现
Spring 的发展历史较为悠久,因此很多资料还在讲解它较旧的实现,这里出于怀旧的原因,把它们都列出来,供大家参考
- ClassPathXmlApplicationContext:从类路径查找 XML 配置文件,创建容器(旧)
- FileSystemXmlApplicationContext:从磁盘路径查找 XML 配置文件,创建容器(旧)
- XmlWebApplicationContext: 传统 SSM 整合时,基于 XML 配置文件的容器(旧)
- AnnotationConfigWebApplicationContext:传统 SSM 整合时,基于 java 配置类的容器(旧)
- AnnotationConfigApplicationContext: Spring boot 中非 web 环境容器(新)
- AnnotationConfigServletWebServerApplicationContext: Spring boot 中 servlet web 环境容器(新)
- AnnotationConfigReactiveWebServerApplicationContext: Spring boot 中 reactive web 环境容器(新)
另外要注意的是,后面这些带有 ApplicationContext 的类都是 ApplicationContext 接口的实现,但它们是组合了 DefaultListableBeanFactory 的功能,并非继承而来。