程序员Java学习笔记Java 杂谈

spring容器加载分析 一容器构造

2018-01-19  本文已影响240人  wangjie2016

目前的spring应用很少有使用XML进行配置的,springboot就是使用AnnotationConfigApplicationContext和AnnotationConfigEmbeddedWebApplicationContext作为非web应用和web应用的容器。所以就以AnnotationConfigApplicationContext为列来分析容器的加载过程。
构造方法:

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        // 构造函数
        this();
        // 向容器注册新的注解Bean
        register(annotatedClasses);
        // 刷新容器, 整个容器的加载都在这个方法中了
        refresh();
}

step 1、this()无参构造方法:

public AnnotationConfigApplicationContext() {
    // 初始化:基于注解的BeanDefinition读取器
    // this就是AnnotatedBeanDefinitionReader中的BeanDefinitionRegistry
    this.reader = new AnnotatedBeanDefinitionReader(this);
    // 初始化:基于路径的BeanDefinition扫描器
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

同时也调用了父类的无参构造方法:

public GenericApplicationContext() {
    // 实例化了默认的beanFactory
    this.beanFactory = new DefaultListableBeanFactory();
}

AnnotatedBeanDefinitionReader初始化方法:

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);
}

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)是一个关键的方法,在这个方法中向向容器中注册6个默认的BeanDefinition:
ConfigurationClassPostProcessor(实现自接口BeanFactoryPostProcessor)
AutowiredAnnotationBeanPostProcessor(实现自接口BeanPostProcessor)
RequiredAnnotationBeanPostProcessor(实现自接口BeanPostProcessor)
CommonAnnotationBeanPostProcessor(实现自接口BeanPostProcessor)
EventListenerMethodProcessor(实现自接口ApplicationContextAware)
DefaultEventListenerFactory(实现自接口EventListenerFactory)
这6个BeanDefinition对Spring至关重要,后面会有更详尽的阐述。

step 2、register(annotatedClasses)向容器注解新的annotatedClasses:
调用的是AnnotatedBeanDefinitionReader中的方法。

public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
    // 创建BeanDefinition
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
    // 判断是否需要跳过(Condition注解)
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }
    // scopeMetadataResolver = AnnotationScopeMetadataResolver
    // 解析注解Bean定义的作用域,
    // 若@Scope("prototype"),则Bean为原型类型  
    // 若@Scope("singleton"),则Bean为单态类型  
    // 默认为singleton
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    // 注解Bean定义生成Bean名称
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    // 处理通用注解 如:Lazy DependsOn 等
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    // 解析限定符注解
    // 主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解  
    // Spring的autowiring默认是按类型装配,如果使用@Qualifier则按名称 和@Resource一样
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            // 如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            //如果配置了@Lazy注解,则设置该Bean为延迟初始化,否则则该Bean为预实例化  
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                // 如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一 个autowiring自动依赖注入装配限定符
                // 该Bean在进autowiring自动依赖注入装配时,根据名称装配限定符指定的Bean 
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    // 创建bean持有类
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    // 根据注解Bean定义类中配置的作用域,创建BeanDefinition相应的代理对象  
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    // 注册BeanDefinition,这个方法中会注册所有的alias
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

annotatedClass已经注册到容器,但是还没有实例化。
this.conditionEvaluator.shouldSkip(abd.getMetadata())) 来判断是否满足Bean创建的条件,如果不满足则跳过。
一个Condition的示例:

/**
 * 条件:Linux操作系统
 */
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
         return context.getEnvironment().getProperty("os.name").contains("Linux");  
    }
}

使用方式:

@Configuration
@Conditional(LinuxCondition.class)
public class LinuxStartupConfig{
    ... ...
}

如果当前的操作系统不是Linux,那么LinuxStartupConfig这个Bean将不会创建。springboot提供的6个@ConditionalOnxxx就基于@Conditional注解和Condition接口实现的。

step 3、refresh() 容器刷新
所有Bean的加载和各种依赖的注入都在这个方法中实现的,之前先了解下两个接口BeanFactoryPostProcessor和BeanPostProcessor,它们都是Spring容器初始化时对外暴露的扩展点。

BeanFactoryPostProcesso接口:

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

只有一个方法postProcessBeanFactory(),它是在容器注册了Bean定义(BeanDefinition)之后,实例化之前执行的。通过这个接口可以获取Bean定义的元数据并且修改它们,如Bean的scope属性、property值等,也可以操作beanFactory。

BeanPostProcessor接口:

public interface BeanPostProcessor {
    // 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务 
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    // 实例化、依赖注入、初始化完毕时执行。 
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

BeanPostProcessor会在Bean实例化完毕后执行,所以任何BeanPostProcessor都是在BeanFactoryPostProcessor之后执行的。
BeanPostProcessor的作用可大了,比如自动注入、各种代理(AOP)等等,凡是对需要Bean进行增强操作的大都可以通过它来实现。

码字不易,转载请保留原文连接https://www.jianshu.com/p/86b53e3f0264

上一篇下一篇

猜你喜欢

热点阅读