likes
comments
collection
share

Spring注解启动:AnnotationConfigApplicationContext原理

作者站长头像
站长
· 阅读数 18

入口代码:

public class SpringAnnotationStarter {
    public static void main(String[] args) {
        //创建一个新的AnnotationConfigApplicationContext,从给定的组件类派生bean定义并自动刷新上下文。
        new AnnotationConfigApplicationContext(SpringAnnotationConfig.class);
    }
}

在上面的测试中,使用的AnnotationConfigApplicationContext来刷新上下文,传入参数是我们定义的配置类。

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}

点进去可以发现,首先是调用空参构造器,然后是注册配置类,最后刷新,所以从这三个步骤进行梳理

1. this()

这就是一个空参构造器。

public AnnotationConfigApplicationContext() {
   this.reader = new AnnotatedBeanDefinitionReader(this);
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}

从代码可以看出,是给reader和scanner两个属性进行赋值。

reader的类型是AnnotatedBeanDefinitionReader ,点进去看源码,这是个适配器,也就是adapter,用于bean类的编程注册,解析带有注解的bean的beanDefinition。在reader的赋值如下:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
   this(registry, getOrCreateEnvironment(registry));
}

传入当前类,并且根据当前环境调用重载的构造进行上下文创建,getOrCreateEnvironment看名字大概就是没有创建,有就获取,这就不看了,直接去关注重载的构造器

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   Assert.notNull(environment, "Environment must not be null");
   this.registry = registry;
   this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
   AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

这里ConditionEvaluator点进去是为context赋值,根据上下文创建一个ConditionContextImpl。

关键在于AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

AnnotationConfigUtils是一个Spring内部工具类,用于识别注解配置类中的bean定义,registerAnnotationConfigProcessors是为在给定的注册表中注册所有后置处理器,也就是PostProcessor。包括一些核心注解,形如:if(!registry.containsBeanDefinition(XXXXXXXXXXXXX))

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
                    BeanDefinitionRegistry registry, @Nullable Object source) {

   //从上下文拿到beanFactory
   DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
   if (beanFactory != null) {
       if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
           beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
       }
       if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
           beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
       }
   }

   Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
            //解析注解ConfigurationClassPostProcessor ,方便后续注册BeanDefinition
   if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
       RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
       def.setSource(source);
       beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
   }
    //解析@Autowired ,方便后续注册BeanDefinition
   if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
       RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
       def.setSource(source);
       beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
   if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
       RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
       def.setSource(source);
       beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
   if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
       RootBeanDefinition def = new RootBeanDefinition();
       try {
           def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                               AnnotationConfigUtils.class.getClassLoader()));
       }
       catch (ClassNotFoundException ex) {
           throw new IllegalStateException(
               "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
       }
       def.setSource(source);
       beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
       RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
       def.setSource(source);
       beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
   }

   if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
       RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
       def.setSource(source);
       beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
   }

   return beanDefs;
}

最后将BeanDefinition集合返回。到这里reader就初始化完成了


然后scanner类型是为给定的bean工厂创建一个新的ClassPathBeanDefinitionScanner

一直往里点可以得到:

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                    Environment environment, @Nullable ResourceLoader resourceLoader) {

   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   this.registry = registry;

   if (useDefaultFilters) {
       registerDefaultFilters();//注册@Component的默认Filters
   }
   setEnvironment(environment);//设置要在解析占位符和评估@Conditional注释组件类时使用的环境。
   setResourceLoader(resourceLoader);//将ResourceLoader设置为用于资源位置。这通常是一个ResourcePatternResolver实现。
}

从这里可以得出,主要用于扫描注解的设置。

2. register(componentClasses);

在上一步中,通过reader和scanner分别对BeanFactory以及核心的注解,过滤器,环境等进行了配置。

register方法中,传入的是我们写的配置类。

跟进,发现调用的是reader的register方法。

@Override
public void register(Class<?>... componentClasses) {
   Assert.notEmpty(componentClasses, "At least one component class must be specified");
   this.reader.register(componentClasses);
}

继续跟进:

public void register(Class<?>... componentClasses) {
   for (Class<?> componentClass : componentClasses) {
       registerBean(componentClass);
   }
}

遍历所有传入的componentClasses,对Bean进行注册,再跟进,我们会进入真正的注册逻辑doRegisterBean

public void registerBean(Class<?> beanClass) {
   doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
                    @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
                    @Nullable BeanDefinitionCustomizer[] customizers) {

   //声明BeanDefinition,下面都是填充属性
   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
   if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
       return;
   }
    //设置用于创建bean实例的回调(可能为null)
   abd.setInstanceSupplier(supplier);
   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
   //作用域
   abd.setScope(scopeMetadata.getScopeName());
   String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    //处理abd中的通用注解,@Lazy、@Primary、@DependsOn、@Role以及@Description
   AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
   //下面这段关于qualifiers判断是否有限定注解@Primary@Lazy
   if (qualifiers != null) {
       for (Class<? extends Annotation> qualifier : qualifiers) {
           if (Primary.class == qualifier) {
               abd.setPrimary(true);
           }
           else if (Lazy.class == qualifier) {
               abd.setLazyInit(true);
           }
           else {
               abd.addQualifier(new AutowireCandidateQualifier(qualifier));
           }
       }
   }
   //处理回调
   if (customizers != null) {
       for (BeanDefinitionCustomizer customizer : customizers) {
           customizer.customize(abd);
       }
   }
    //将abd封装成BeanDefinitionHolder,然后对BeanDefinition注册
   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
   //代理
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
   //向BeanFactory进行注册
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

到这里相当于把我们写的配置注册到Spring了。

3. refresh();

这个方法,点进去就是一个refresh方法,对应Spring的初始化中的refresh,org.springframework.context.support.AbstractApplicationContext#refresh,对应着Spring生命周期 下面这段是之前学Spring的时候在网上找的,大致流程如下:

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // 准备此上下文以进行刷新、设置其启动日期和活动标志以及执行任何属性源的初始化。
        prepareRefresh();//刷新前的预处理

        // 创建初始化BeanFactory,这个过程中loadBeanDefinitions()方法,输入beanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
         //  1.设置BeanFactory的类加载器为ApplicationContex的类加载器
		// 2.设置beanFacory的语言表达式处理器

        try {
            this.postProcessBeanFactory(beanFactory);
            // 执行BeanFactoryPostProcessor的方法,BeanFactory的后置处理器 
            // 在BeanFactory标准初始化之后执行的,调用各种BeanFactoryPostProcessor
            this.invokeBeanFactoryPostProcessors(beanFactory);
            // 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程
            this.registerBeanPostProcessors(beanFactory);
            // 初始化MessageSource组件(做国际化功能;消息绑定,消息解析).
            this.initMessageSource();
            // 初始化上下文的事件机制
            this.initApplicationEventMulticaster();
            // 可以用于子类实现在容器刷新时自定义逻辑初始化
            this.onRefresh();
            // 注册时间监听器,将ApplicationListener注册到容器中来
            this.registerListeners();
            // 初始化所有剩下的单实例bean,单例bean在初始化容器时创建。
            this.finishBeanFactoryInitialization(beanFactory);
            // 发布完成事件,结束初始化过程
            this.finishRefresh();
        }

        catch (BeansException ex) {
            ...
            }
    }
}

简易流程图

Spring注解启动:AnnotationConfigApplicationContext原理