Spring refresh概述
refresh 是AbstractApplicationContext
中的一个方法,负责初始化 ApplicationContext 容器,容器必须调用 refresh 才能正常工作。它的内部主要会调用 12 个方法,我们把它们称为 refresh 的 12 个步骤。功能分类:
- 1 为准备环境
- 2 3 4 5 6 为准备 BeanFactory
- 7 8 9 10 12 为准备 ApplicationContext
- 11 为初始化 BeanFactory 中非延迟单例 bean
准备环境
1. prepareBeanFactory
这一步创建和准备了 Environment 对象,它作为 ApplicationContext 的一个成员变量
Environment 对象的作用之一是为后续 @Value,值注入时提供键值
Environment 分成三个主要部分
- systemProperties - 保存 java 环境键值
- systemEnvironment - 保存系统环境键值
- 自定义 PropertySource - 保存自定义键值,例如来自于 *.properties 文件的键值
测试获取环境变量
static class Bean1 {
@Value("hello")
private String name;
@Value("${jdbc.username}")
private String javaHome;
@Value("#{'class version:' + '${java.class.version}'}")
private String expression;
}
通过
DependencyDescriptor
指定取Bean1中 name成员变量的 value值
// 1) 获得 @Value 的值
System.out.println("=======================> 仅获取 @Value 值");
QualifierAnnotationAutowireCandidateResolver resolver = new QualifierAnnotationAutowireCandidateResolver();
//DependencyDescriptor 指定取Bean1中 name成员变量的 value值
Object name = resolver.getSuggestedValue(new DependencyDescriptor(Bean1.class.getDeclaredField("name"), false));
System.out.println(name);
通过
StandardEnvironment
解析 #{}变量的值
// 2) 解析 @Value 的值
System.out.println("=======================> 获取 @Value 值, 并解析${}");
Object javaHome = resolver.getSuggestedValue(new DependencyDescriptor(Bean1.class.getDeclaredField("javaHome"), false));
System.out.println(javaHome);
System.out.println(getEnvironment().resolvePlaceholders(javaHome.toString()));
private static Environment getEnvironment() throws IOException {
StandardEnvironment env = new StandardEnvironment();
//添加自定义文件的位置
env.getPropertySources().addLast(new ResourcePropertySource("jdbc", new ClassPathResource("jdbc.properties")));
return env;
}
通过
StandardBeanExpressionResolver
解析 SpEL 表达式
System.out.println("=======================> 获取 @Value 值, 并解析#{}");
Object expression = resolver.getSuggestedValue(new DependencyDescriptor(Bean1.class.getDeclaredField("expression"), false));
System.out.println(expression);
String v1 = getEnvironment().resolvePlaceholders(expression.toString());
System.out.println(v1);
System.out.println(new StandardBeanExpressionResolver().evaluate(v1, new BeanExpressionContext(new DefaultListableBeanFactory(),null)));
准备BeanFactory
2. obtainFreshBeanFactory
这一步获取(或创建) BeanFactory,它也是作为 ApplicationContext 的一个成员变量
BeanFactory 的作用是负责 bean 的创建、依赖注入和初始化,bean 的各项特征由BeanDefinition
定义
- BeanDefinition 作为 bean 的设计蓝图,规定了 bean 的特征,如单例多例、依赖关系、初始销毁方法等
- BeanDefinition 的来源有多种多样,可以是通过 xml 获得、配置类获得、组件扫描获得,也可以是编程添加
所有的 BeanDefinition 会存入 BeanFactory 中的 beanDefinitionMap 集合
演示获取BeanDefinition方式 重点:
ConfigurationClassPostProcessor
BeanFactory后置处理器处理 @Bean注解ClassPathBeanDefinitionScanner
: 扫描指定包下标注了@Component注解的包
public class TestBeanDefinition {
public static void main(String[] args) {
System.out.println("========================> 一开始");
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
System.out.println(Arrays.toString(beanFactory.getBeanDefinitionNames()));
System.out.println("========================> 1) 从 xml 获取 ");
//指定XML中读取到的BeanDefinition放入这个 beanFactory
XmlBeanDefinitionReader reader1 = new XmlBeanDefinitionReader(beanFactory);
reader1.loadBeanDefinitions(new ClassPathResource("bd.xml"));
System.out.println(Arrays.toString(beanFactory.getBeanDefinitionNames()));
System.out.println("========================> 2) 从配置类获取 ");
//手动注册配置类的BeanDefinition
beanFactory.registerBeanDefinition("config1", BeanDefinitionBuilder.genericBeanDefinition(Config1.class).getBeanDefinition());
//需要添加 ConfigurationClassPostProcessor 后置处理器才能解析 @Bean 注解
ConfigurationClassPostProcessor postProcessor = new ConfigurationClassPostProcessor();
postProcessor.postProcessBeanDefinitionRegistry(beanFactory);
System.out.println(Arrays.toString(beanFactory.getBeanDefinitionNames()));
System.out.println("========================> 3) 扫描获取 ");
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
scanner.scan("day04.refresh.sub");
System.out.println(Arrays.toString(beanFactory.getBeanDefinitionNames()));
}
static class Bean1 {
}
static class Bean2 {
}
static class Config1 {
@Bean
public Bean2 bean2() {
return new Bean2();
}
}
}
3. prepareBeanFactory
这一步会进一步完善 BeanFactory,为它的各项成员变量赋值
beanExpressionResolver
用来解析 SpEL,常见实现为 StandardBeanExpressionResolver
propertyEditorRegistrars
会注册类型转换器
- 它在这里使用了 ResourceEditorRegistrar 实现类
- 并应用 ApplicationContext 提供的 Environment 完成 ${ } 解析
registerResolvableDependency
来注册 beanFactory 以及 ApplicationContext,让它们也能用于依赖注入
beanPostProcessors
是 bean 后处理器集合,会工作在 bean 的生命周期各个阶段,此处会添加两个:
- ApplicationContextAwareProcessor 用来解析 Aware 接口
- ApplicationListenerDetector 用来识别容器中 ApplicationListener 类型的 bean
4. postProcessBeanFactory
这一步是空实现,留给子类扩展。
- 一般 Web 环境的 ApplicationContext 都要利用它注册新的 Scope,完善 Web 下的 BeanFactory
这里体现的是模板方法设计模式
5. invokeBeanFactoryPostProcessors
这一步会调用 beanFactory 后处理器
beanFactory 后处理器,充当 beanFactory 的扩展点,可以用来补充或修改 BeanDefinition
常见的 beanFactory 后处理器有
- ConfigurationClassPostProcessor – 解析 @Configuration、@Bean、@Import、@PropertySource 等
- PropertySourcesPlaceHolderConfigurer – 替换 BeanDefinition 中的 ${ }
- MapperScannerConfigurer – 补充 Mapper 接口对应的 BeanDefinition
6. registerBeanPostProcessors
这一步是继续从 beanFactory的 beanDefinitionMap集合中找出 bean 后处理器,添加至 beanPostProcessors 集合中
bean 后处理器,充当 bean 的扩展点,可以工作在 bean 的实例化、依赖注入、初始化阶段,常见的有:
- AutowiredAnnotationBeanPostProcessor 功能有:解析 @Autowired,@Value 注解
- CommonAnnotationBeanPostProcessor 功能有:解析 @Resource,@PostConstruct,@PreDestroy
- AnnotationAwareAspectJAutoProxyCreator 功能有:为符合切点的目标 bean 自动创建代理
注意:
这一步只是注册Bean后置处理器,在后续Bean创建过程中才用到
public class TestBeanPostProcessor {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
//标准的beanFactory没有后置处理器的功能
DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
beanFactory.registerBeanDefinition("bean1", BeanDefinitionBuilder.genericBeanDefinition(Bean1.class).getBeanDefinition());
beanFactory.registerBeanDefinition("bean2", BeanDefinitionBuilder.genericBeanDefinition(Bean2.class).getBeanDefinition());
beanFactory.registerBeanDefinition("bean3", BeanDefinitionBuilder.genericBeanDefinition(Bean3.class).getBeanDefinition());
beanFactory.registerBeanDefinition("aspect1", BeanDefinitionBuilder.genericBeanDefinition(Aspect1.class).getBeanDefinition());
//添加bean的后置处理器
beanFactory.registerBeanDefinition("processor1",
BeanDefinitionBuilder.genericBeanDefinition(AutowiredAnnotationBeanPostProcessor.class).getBeanDefinition());
beanFactory.registerBeanDefinition("processor2",
BeanDefinitionBuilder.genericBeanDefinition(CommonAnnotationBeanPostProcessor.class).getBeanDefinition());
beanFactory.registerBeanDefinition("processor3",
BeanDefinitionBuilder.genericBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class).getBeanDefinition());
context.refresh();
beanFactory.getBean(Bean1.class).foo();
}
static class Bean1 {
Bean2 bean2;
Bean3 bean3;
@Autowired
public void setBean2(Bean2 bean2) {
System.out.println("发生了依赖注入..." + bean2);
this.bean2 = bean2;
}
@Resource
public void setBean3(Bean3 bean3) {
System.out.println("发生了依赖注入..." + bean3);
this.bean3 = bean3;
}
public void foo() {
System.out.println("foo");
}
}
static class Bean2 {
}
static class Bean3 {
}
@Aspect
static class Aspect1 {
@Before("execution(* foo())")
public void before() {
System.out.println("before...");
}
}
}
准备 ApplicationContext
7. initMessageSource
这一步是为 ApplicationContext 添加 messageSource 成员,实现国际化功能
去 beanFactory的beanDefinitionlMap 内找名为 messageSource 的 bean( 需要实现MessageSource接口),如果没有,则提供空的 MessageSource 实现,表示不支持国际化
8. initApplicationContextEventMulticaster
这一步为 ApplicationContext 添加事件广播器成员,即 applicationContextEventMulticaster
它的作用是发布事件给监听器
- 去 beanFactory 找名为
applicationEventMulticaster
的 bean 作为事件广播器,若没有,会创建默认的事件广播器- 之后就可以调用
ApplicationContext.publishEvent
(事件对象) 来发布事件- AbstractApplicationEventMulticaster中的 defaultRetriever集合维护了所有的监听器,发布事件时遍历这个集合找到对事件感兴趣的监听器
9. onRefresh
这一步是空实现,留给子类扩展
SpringBoot 中的子类在这里准备了 WebServer,即内嵌 web 容器
体现的是模板方法设计模式
registerListeners
这一步会从多种途径找到事件监听器,并添加至 applicationEventMulticaster
事件监听器顾名思义,用来接收事件广播器发布的事件,有如下来源
- 事先编程添加的
- 来自容器中的 bean
- 来自于 @EventListener 的解析
要实现事件监听器,只需要实现 ApplicationListener 接口,重写其中 onApplicationEvent(E e) 方法即可
12. finishRefresh
这一步会为 ApplicationContext 添加 lifecycleProcessor 成员,用来控制容器内需要生命周期管理的 bean
如果容器中有名称为 lifecycleProcessor 的 bean 就用它,否则创建默认的生命周期管理器
准备好生命周期管理器,就可以实现
- 调用 context 的 start,即可触发所有实现 LifeCycle 接口 bean 的 start
- 调用 context 的 stop,即可触发所有实现 LifeCycle 接口 bean 的 stop
发布 ContextRefreshed 事件,整个 refresh 执行完成
初始化 BeanFactory 中非延迟单例 bean
11. finishBeanFactoryInitialization
这一步会将 beanFactory 的成员补充完毕,并初始化所有非延迟单例 bean
conversionService 也是一套转换机制,作为对 PropertyEditor 的补充
embeddedValueResolvers 即内嵌值解析器,用来解析 @Value 中的 ${ },借用的是 Environment 的功能
singletonObjects 即单例池,缓存所有单例对象(只有非延迟的单例对象才会从beanDefinitionMap中创建到singletonObjects中, 延迟创建的对象只有第一次使用到才会创建
)
- 对象的创建都分三个阶段(创建–> 依赖注入 --> 初始化),每一阶段都有不同的 bean 后处理器参与进来,扩展功能