(一)Spring之容器启动流程

107 阅读5分钟

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处理器。

处理顺序:

  1. 先去处理自己的定义的registry。
  2. 再去处理工厂原来就有的registry。
    • 调用实现了PriortyOrder接口的registry处理器的注册方法。
    • 调用实现了Order接口的registry处理器的注册方法
    • 递归调用其他的registry处理器的注册方法。
  3. 调用registry处理器的postprocess方法。
  4. 调用regular处理器的postprocess方法。
  5. 处理剩下的regular处理器的postprocess方法。(上面的regular处理器只是一部分,是用户自定义的那部分)。

registerBeanPostProcessors(beanFactory);注册bean的后置处理器,

  1. 先注册实现了PriorityOrdered接口的后置处理器。
  2. 再注册实现了Ordered接口的后置处理器。
  3. 再注册非排序类的后置处理器。
  4. 注册regular类型的后置处理器。

int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; 容器内部的后置处理器数量,处理器类型的bd数量,但是为什么要加一呢??? BeanPostProcessorChecker这个是干什么的??????? ApplicationListenerDetector这个是干什么的??????

initMessageSource();支持国际化。

initApplicationEventMulticaster();让spring容器成为一个广播器。

onRefresh();AnnotationConfigApplicationContext这个类中没用。

registerListeners();注册一些监听器,

finishBeanFactoryInitialization(beanFactory);创建非懒加载的bean。

  1. 配置一个转换器。
    • 先去看看有没有ConversionService这个bean,有的话就给BeanFactory装上。
    • 这里有一个containsbean方法,即使你没有真正的bean,只有beandefintion也认为你是有这个bean的。
  2. 配置一个解析器。
    • 之前没有配置value解析器,就配上一个默认的value解析器。
  3. 获取编译织入器。
  4. 缓存下所有的beandefinition元数据。
  5. 加载所有的非懒加载的bean。
    • 如果是factorybean,那么根据配置条件获取bean
    • 如果不是factorybean,那么就直接获取bean。
    • 最后会拿单例做一些事情。

beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));