spring容器启动流程
这一片主要讲了spring是怎么启动的,启动的时候都去做了哪些事情。
- spring容器启动流程
- 主流程
- 次流程
- spring容器启动流程中的核心类
- spring容器启动流程源码解析
spring容器启动流程
主流程:
1.创建BeanFactory
2.注册默认的BeanFactory后置处理器
3.执行BeanFactory中的BeanFactory后置处理器
4.注册Bean的后置处理器
5.生成非懒加载的单例bean
次流程:
1.国际化
2.资源加载
3.广播器初始化
4.获取运行时环境
5.发布事件
spring容器启动流程核心类
BeanDefinitionReader。简称bd读取器,bd读取器相当于spring容器的基础设施。 有三种beandefinition的读取器,分别是AnnotatedBeanDefinitionReader、XmlBeanDefinitionReader、ClassPathBeanDefinitionScanner。
- AnnotatedBeanDefinitionReader。可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解。 还会处理类上的一些注解,比如@Conditional,@Scope、@Lazy、@Primary、@DependsOn、 @Role、@Description。这里要额外讲一下的是,在构造AnnotatedBeanDefinitionReader,会默认注册一些beanfactory后置处理器,其中最重要的就是ConfigurationClassPostProcessor,这相当于利用了工厂的扩展达到了解析配置类的目的。
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new
AnnotatedBeanDefinitionReader(applicationContext);
// User.class BeanDefinition
annotatedBeanDefinitionReader.register(User.class);
applicationContext.refresh();
User user = (User) applicationContext.getBean("user");
user.test();
}
- XmlBeanDefinitionReader。读取xml的文件中的bf
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
System.out.println(context.getBean("user"));
}
- ClassPathBeanDefinitionScanner。和BeanDefinitionReader类似,它可以 进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component 注解,那么就会把这个类解析为一个BeanDefinition。
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.scan("com.zhouyu");
System.out.println(context.getBean("userService"));
}
BeanFactory。简称bean工厂,所有的bean都放在bean工厂里面管理。 DefaultListableBeanFactory是spring容器中默认的工厂。
ApplicationContext。就是我们说的spring容器,有两个实现,AnnotationConfigApplicationContext和ClassPathXmlApplicationContext。
类型转化
- PropertyEditor。这其实是JDK中提供的类型转化工具类
public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {
@Override
public void setAsText(String text) throws IllegalArgumentException {
User user = new User();
user.setName(text);
this.setValue(user);
} }
- ConversionService。Spring中提供的类型转化服务,它比PropertyEditor更强大。
public class StringToUserConverter implements ConditionalGenericConverter {
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
return sourceType.getType().equals(String.class) &&
targetType.getType().equals(User.class);
}
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(String.class, User.class));
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor
targetType) {
User user = new User();
user.setName((String)source);
return user;
} }
- TypeConverter。整合了PropertyEditor和ConversionService的功能,是Spring内部用的。
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
//typeConverter.setConversionService(conversionService);
User value = typeConverter.convertIfNecessary("1", User.class);
System.out.println(value);
组件过滤器
- ExcludeFilter。就是说使用注解扫描的时候,即使你有@Component,也会过滤掉指定的类。
- IncludeFilter。就是说扫描的时候会包括在内,即使你没有@Component。
元数据读取器
- MetadataReader。默认实现类为SimpleMetadataReader,需要注意的是,去解析类时,使用的ASM技术。 它可以解析出ClassMetadata、 AnnotationMetadata。
spring容器启动流程源码解析
构造spring容器
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry;
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotationConfigApplicationContext继承了GenericApplicationContext。默认会去构造一个bean工厂。
new AnnotatedBeanDefinitionReader(this);会去创建一个bdreader,有类打了@Component这些注解,reader就会解析出相应的beandefinition。
new ClassPathBeanDefinitionScanner(this);会去创建一个bdscaner,会去扫描指定包下类,如果有@Component这些注解,就会解析出相应的beandefinition。
说白了就是构造了一个bean工厂,然后给这个bean工厂摁了两个bd解析器。
接着是refresh方法
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
prepareRefresh();
- 主要做一些校验环境参数的事情。
- 恢复监听器到初次refresh的状态。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 它会执行GenericApplicationContext中的refreshBeanFactory(),这个方法就只是给bean工厂设置了一个id。 然后返回一个bean工厂。
invokeBeanFactoryPostProcessors(beanFactory);执行bean工厂的后置处理逻辑。 有两类beanfactorypostprocessor。registry类型的beanfactorypostprocessor,简称registry处理器,regular类型的beanfactorypostprocessor,简称regular处理器。
处理顺序:
- 先去处理自己的定义的registry。
- 再去处理工厂原来就有的registry。
- 调用实现了PriortyOrder接口的registry处理器的注册方法。
- 调用实现了Order接口的registry处理器的注册方法
- 递归调用其他的registry处理器的注册方法。
- 调用registry处理器的postprocess方法。
- 调用regular处理器的postprocess方法。
- 处理剩下的regular处理器的postprocess方法。(上面的regular处理器只是一部分,是用户自定义的那部分)。
registerBeanPostProcessors(beanFactory);注册bean的后置处理器,
- 先注册实现了PriorityOrdered接口的后置处理器。
- 再注册实现了Ordered接口的后置处理器。
- 再注册非排序类的后置处理器。
- 注册regular类型的后置处理器。
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; 容器内部的后置处理器数量,处理器类型的bd数量,但是为什么要加一呢??? BeanPostProcessorChecker这个是干什么的??????? ApplicationListenerDetector这个是干什么的??????
initMessageSource();支持国际化。
initApplicationEventMulticaster();让spring容器成为一个广播器。
onRefresh();AnnotationConfigApplicationContext这个类中没用。
registerListeners();注册一些监听器,
finishBeanFactoryInitialization(beanFactory);创建非懒加载的bean。
- 配置一个转换器。
- 先去看看有没有ConversionService这个bean,有的话就给BeanFactory装上。
- 这里有一个containsbean方法,即使你没有真正的bean,只有beandefintion也认为你是有这个bean的。
- 配置一个解析器。
- 之前没有配置value解析器,就配上一个默认的value解析器。
- 获取编译织入器。
- 缓存下所有的beandefinition元数据。
- 加载所有的非懒加载的bean。
- 如果是factorybean,那么根据配置条件获取bean
- 如果不是factorybean,那么就直接获取bean。
- 最后会拿单例做一些事情。
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));