コアコンテナのスプリング(C) - を開始する準備ができてのApplicationContextコンテキスト

序文

Springコンテナの概念の前に導入され、コアを2つのカテゴリにまとめることができますたBeanFactoryとApplicationContextの、ApplicationContextのはたBeanFactoryのすべての機能が含まれていますが、また、コンテナの機能を拡張するだけでなくたBeanFactoryから継承されました。後、彼はSSM期間とSpringBoot期間のApplicationContextを起動する方法について説明します。登録豆、豆及び他の注射:終わりに、我々は指摘し、ApplicationContextのコア実際リフレッシュ方法は、容器の機能の一連のような方法で実装されています。

コンテナは、コア機能、準備作業環境の最初のシリーズを達成する前にリフレッシュ方法では、我々は、現在のオペレーティング環境のためにこの部分の詳細な議論をSpringBoot。

注:2.0.3.RELEASEに使用されるこの記事のSpringBootバージョン、その春バージョン5.0.7.RELEASE

テキスト

インタフェースで定義されConfigurableApplicationContextリフレッシュ方法は、抽象クラスAbstractApplicationContext実装され、10個のサブ方法からなる方法は、サブ方法は、その職務を行う、いくつかのサブ方法はAbstractApplicationContextサブクラスは機能を強化するために延びています。このうち、最初の4つのサブコンテキスト方法は、主に調剤。

最初のステップ:prepareRefresh

私たちは、prepareRefresh方法のリフレッシュが議論を開始します起動します。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 初始化上下文环境,就是记录下容器的启动时间、活动状态等
        prepareRefresh();

        ...
    }
}

この方法は、抽象クラスのサブクラスは、拡張サブクラスのメソッドを拡張することがAbstractApplicationContextされています。

画像

このため、デモ環境のSpringBootは、以前の私たちはSpringBootは、そのようなので、上のサーブレットのWeb、反応性のWebとして、現在のWebアプリケーションの種類に基づいて、異なるコンテキストオブジェクトを作成し、について話しています。コンテキストオブジェクトがAnnotationConfigServletWebServerApplicationContextを作成しているので、ここで示された、サーブレットのWebアプリケーションです。PrepareRefreshクラスメソッドが実行されます。

public class AnnotationConfigServletWebServerApplicationContext
        extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {

    ...
    
    @Override
    protected void prepareRefresh() {
    
        // 清除 Class 的元数据缓存。底层用 Map 保存元数据,执行 Map 的 clear 方法
        this.scanner.clearCache();
        
        // 调用父类,也就是 AbstractApplicationContext 的 prepareRefresh 方法
        super.prepareRefresh();
    }
    ...     
}
public abstract class AbstractApplicationContext {
    
    ...
    
    private long startupDate;
    
    private final AtomicBoolean active = new AtomicBoolean();

    private final AtomicBoolean closed = new AtomicBoolean();

    private Set<ApplicationEvent> earlyApplicationEvents;

    ...

    protected void prepareRefresh() {
        
        // 记录此上下文开始时的系统时间(以毫秒为单位)
        this.startupDate = System.currentTimeMillis();
        
        // 记录此上下文是否已关闭,这里设置为未关闭
        this.closed.set(false);
        
        // 记录此上下文是否处于活动状态,这里设置为活动状态
        this.active.set(true);
    
        if (logger.isInfoEnabled()) {
            logger.info("Refreshing " + this);
        }
    
        // 这也是交由子类扩展的方法。具体子类为 GenericWebApplicationContext,主要是初始化属性源,
        // 将 ServletContext 和 ServletConfig 属性配置添加到 Environment 环境上下文中
        initPropertySources();
    
        // 校验 Environment 中那些必备的属性配置是否存在,不存在则抛异常。
        getEnvironment().validateRequiredProperties();
    
        // 创建 ApplicationEvent 事件集合
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }

}

リフレッシュを実行するprepareRefresh方法が終了すると、録画開始時刻は必須の属性があるかどうかを確認するために、主要な血管、アクティブ状態です。このうち、環境設定環境については、記事の前のSpringBootシリーズで詳細に説明されている、興味のある学生は、自分で読むことができます。

ステップ2:obtainFreshBeanFactory

次いで、この方法は、obtainFreshBeanFactoryをリフレッシュするために進み、

public abstract class AbstractApplicationContext {
    
    ...
    
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            
            ...
            
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            ...
        }
    }
    ...
    
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 该方法也是由子类扩展,其子类有 AbstractRefreshableApplicationContext 和 GenericApplicationContext,
        // 因当前是 Servlet Web 应用,所以执行的是 GenericApplicationContext 中的 refreshBeanFactory 方法。
        // 该方法主要设置 BeanFactory 的 serializationId 属性值,也就是序列化id
        refreshBeanFactory();
        
        // 通过 getBeanFactory 返回 BeanFactory 对象。同样也是由子类扩展,调用的是 GenericApplicationContext 类中的 getBeanFactory 方法。
        // 返回的是 DefaultListableBeanFactory 。
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }
    
    ...
}

obtainFreshBeanFactory方法は非常にシンプルですが、現在の非サーブレットのWebアプリケーションならば、実行はそれ以上に複雑になるrefreshBeanFactory方法でAbstractRefreshableApplicationContextは、ここでそれを議論していない、です。その後、メソッド戻り、下から見ることができる、さらにオブジェクトをたBeanFactoryのApplicationContextたBeanFactory基づいSpringコンテナが徐々に拡張された機能です。

第三段階:prepareBeanFactory

次いで、この方法は、prepareBeanFactoryをリフレッシュするために進みます。この方法は、主にprepareBeanFactoryたBeanFactoryは依存関係とポストプロセッサを無視するように、様々なクラスローダのニーズを含むいくつかの構成を、行う、およびパーサのようなものです

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
            
        ...
        
        prepareBeanFactory(beanFactory);
        ... 
    }
    ...
}

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置表达式解析器,主要用来解析 EL 表达式; Bean 初始化完成后填充属性时会用到
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 设置属性注册解析器,主要用来解析 Bean 中的各种属性类型,如 String、int 等
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    // 添加一个后置处理器:ApplicationContextAwareProcessor。
    // 该后置处理器用于向实现了 Aware 系列接口的 bean 设置相应属性。
    // (后置处理器和 Aware 接口也是比较核心的概念,后面会有文章详细讨论)
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    
    // 以下接口,在自动注入时会被忽略,其都是 Aware 系列接口
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // 当以下特殊的 Bean 需自动注入时,指定其注入的类型 。
    // 如:注入 BeanFactory 时,注入的类型对象为 ConfigurableListableBeanFactory 。
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 添加 ApplicationListenerDetector 后置处理器。
    // 该后置处理器用来检测那些实现了 ApplicationListener 接口的 bean,并将其添加到应用上下文的事件广播器上。
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 判断容器中是否存在 loadTimeWeaver Bean,如果存在则上下文使用临时的 ClassLoader 进行类型匹配。
    // 集成 AspectJ 时会用到 loadTimeWeaver 对象。
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册和环境相关的 Bean,如 environment、systemProperties、systemEnvironment
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

prepareBeanFactory方法では、主たBeanFactory一連のそのような自動注入を無視するようにインターフェイスを追加するように、属性項目を追加し、BeanPostProcessorポストプロセッサ、特別な手動登録部豆及び環境関連豆を添加します。

ステップ4:postProcessBeanFactory

調製方法の文脈においてpostProcessBeanFactory最後のステップは、主プロセッサ、豆および構成に関連するWeb要求を登録するために使用されます。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        
        ...
        
        postProcessBeanFactory(beanFactory);
        ...   
    }
}

この方法はまた、サブクラスによって拡張され、サブクラスはこのメソッドを実装しています。

画像
持っているが、現在、サーブレットのWebアプリケーションなので、ApplicationContextのコンテキストの作成がAnnotationConfigServletWebServerApplicationContext、クラスのpostProcessBeanFactory実行メソッドで、前に言いました。

public class AnnotationConfigServletWebServerApplicationContext
        extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {

    private final AnnotatedBeanDefinitionReader reader;

    private final ClassPathBeanDefinitionScanner scanner;

    private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();

    private String[] basePackages;
    
    ...
    
    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 先执行父类 ServletWebServerApplicationContext 的 postProcessBeanFactory 方法。
        // 跳转到 1 查看父类实现
        super.postProcessBeanFactory(beanFactory);
        
        // basePackages 存储的是类路径。先判断是否为 null,不为 null 则通过 ClassPathBeanDefinitionScanner 的 scan 方法
        // 扫描该路径下符合条件的 Class,并将 Class 信息包装成 BeanDefinition 注册到容器中,
        // 当然,这里没有指定扫描路径,所以不会进入这个 if。
        // (BeanDefinition 概念会在后面章节详细讨论)
        if (this.basePackages != null && this.basePackages.length > 0) {
            this.scanner.scan(this.basePackages);
        }
        
        // annotatedClasses 存储的 Class 集合。先判断该集合是否为空,不为空则通过
        // AnnotatedBeanDefinitionReader 的 register 方法将 Class 信息包装成 BeanDefinition 注册到容器中,
        // 这里同样没有设置 Class 集合内容,所以不会进入这个 if。
        if (!this.annotatedClasses.isEmpty()) {
            this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
        }
    }       
}

1、
public class ServletWebServerApplicationContext extends GenericWebApplicationContext
        implements ConfigurableWebServerApplicationContext {
    ...

    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 添加 BeanPostProcessor 后置处理器:WebApplicationContextServletContextAwareProcessor,
        // 该后置处理器主要是从 ConfigurableWebApplicationContext 上下文中获取 ServletContext 和 ServletConfig 对象
        beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
        
        // 添加一个 忽略自动注入的接口
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    }
    ...         
}

同様の動作および方法は、postProcessBeanFactoryフロント行わ添加し、ポストプロセッサインタフェースは自動的に無視さ注入しました。

概要

準備作業のApplicationContextの文脈では、基本的には、たBeanFactoryにおけるポストプロセッサのシリーズを追加登録し、特殊な豆を設定するには、主に、終了した自動的に注入されたインターフェースを無視しました。後資料のこの部分は、ステップバイステップについて説明する認識シリアルインタフェース、BeanPostProcessorポストプロセッサ、BeanDefinition、:それはまた、3つのコアコンポーネントSpringコンテナと呼びます。次Springコンテナは、コア機能について説明します。




これらは、この章の内容であるか、あるいは前方に入れてください追加する必要があります記事に誤りがある場合、私は感謝しています。

おすすめ

転載: www.cnblogs.com/loongk/p/12233417.html