Spring4.xソースコードシリーズ5-Beanのライフサイクル

1.フロンティア

Beanの作成Beanのロードを学習した後、Spring IOCコンテナーによる管理対象オブジェクトBeanの管理について学習しました。また、BeanのライフサイクルもSpringIOCコンテナーによって完全に管理されます。Springのiocコンテナは非常に強力で、Spring'sBeanの作成と管理を担当します。Spring Beanは、Springアプリケーション全体の非常に重要な部分です。SpringBeanのライフサイクルを理解すると、Springフレームワーク全体を理解するのに役立ちます。

BeanFactoryApplicationContextは、Springの2つの非常に重要なコンテナーであり、それらの関数は次のとおりです。

BeanFactory作成Beanと依存性注入のサポートを提供します

ApplicationContextBeanFactoryの機能に加えて、イベント伝播リソースアクセス国際化されたメッセージアクセスなどのいくつかの拡張機能が追加されました

Beanの完成したライフサイクルを次の図に示します。

以下に、ApplicationContextコンテナとBeanFactoryコンテナのBeanのライフサイクルをそれぞれ説明します。

2、ApplicationContextBeanのライフサイクル

まず、以下に示すように、ApplicationContextBeanのライフサイクル図を確認します。

ApplicationContextコンテナ、Beanのライフサイクルプロセスはおおよそ次のとおりです。

2.1 Beanのインスタンス化(BeanインスタンスBeanWrapperの作成)

ApplicationContextコンテナーの場合、コンテナーが開始されると、すべてのBeanがインスタンス化され、コンテナーはBeanDefinition(Bean定義)オブジェクトの情報を取得してインスタンス化します。この手順は、初期化や依存性注入を行わない単純なインスタンス化であることに注意してください。作成されたBeanインスタンスはBeanWrapperオブジェクトにパッケージ化されます。BeanWrapperはオブジェクトプロパティを設定するためのインターフェイスを提供するため、Beanプロパティを設定するためのリフレクションメカニズムの使用を回避します。

2.2プロパティの入力(Beanプロパティの初期化)

インスタンス化されたオブジェクトBeanWrapperは現時点ではネイティブ状態であり、依存性注入を含むプロパティ設定は実行されていません。次に、SpringはBeanDefinitionの情報に基づいて依存性注入を実行します。
そして、BeanWrapperが提供する属性設定インターフェースを介した完全な依存性注入

2.3xxxAwareインターフェースを挿入します

Springは、以下に示すように、オブジェクトがxxxAwareインターフェースを実装しているかどうかを検出し、関連するxxxAwareインスタンスをBeanに注入します。

1)BeanがBeanNameAwareインターフェースを実装している場合、BeanはインターフェースのsetBeanNameメソッドを呼び出し、BeanのIDを渡すため、Beanは構成ファイルで独自のIDを取得します。

2)BeanがBeanFactoryAwareインターフェースを実装している場合、インターフェースのsetBeanFactoryメソッドがBeanのBeanFactoryに渡されるため、Beanはそれが含まれているBeanFactoryオブジェクトを取得します。

3)BeanがApplicationContextAwareインターフェースを実装している場合、BeanはインターフェースのsetApplicationContextメソッドを呼び出し、BeanのApplicationContextを渡すため、Beanは独自のApplicationContextオブジェクトを取得します。

2.4BeanPostProcessorインターフェース

上記の3つの手順を実行すると、Beanオブジェクトが作成されます。オブジェクトを使用する前にカスタム処理を実行する場合は、次の2つの重要なメソッドを提供するBeanPostProcessorインターフェイスを実装して処理を完了できます。

postProcessBeforeInitialization(Object bean、String beanName):現在初期化されているBeanとBeanNameを渡し、この時点でBeanをカスタマイズできます。このメソッドはInitialzationBeanインターフェースメソッドの前に実行されるため、前処理と呼ばれます。

postProcessAfterInitialization(Object bean、String beanName):現在初期化されているBeanとBeanNameを渡し、この時点でBeanをカスタマイズできます。このメソッドはInitialzationBeanインターフェースメソッドが呼び出された後に実行されるため、post-と呼ばれます。処理

2.5InitialzationBeanインターフェースとinit-methodメソッド

BeanPostProcessorの前処理後、BeanがInitialzationBeanインターフェースを実装している場合、InitializingBeanインターフェースのafterPropertiesSetメソッドが呼び出されます。

InitializingBeanインターフェースには、パラメーターを持たないafterPropertiesSet()という1つのメソッドしかないため、Beanで処理を行うことはできませんが、いくつかの追加のビジネスロジックを実装できます。

クライアントコードの侵入を減らすために、SpringはBeanの構成用のinit-method属性も提供します。これにより、ユーザーは実行するメソッドを構成できます。

この手順の後、Beanを正式に使用できます。スコープがシングルトンタイプのBeanの場合、BeanのインスタンスはSpring IOCコンテナーにキャッシュされ、スコープがプロトタイプタイプのBeanの場合、新しいインスタンスがキャッシュされます。オブジェクトと呼ばれるたびに作成され、そのライフサイクルは呼び出し元に渡されて管理され、Springコンテナによって管理されなくなります。

2.6DisposableBeanインターフェースとdestroy-meythodメソッド

コンテナが閉じられた後、BeanがDisposableBeanインターフェースを実装している場合、インターフェースのdestroyメソッドが呼び出されてBeanが破棄されます。

同様に、クライアントコードの侵入を減らすために、SpringはBeanの構成にdestroy-method属性も提供します。これにより、ユーザーはBeanが破棄された後に実行されるメソッドを構成できます。

この時点で、Bean全体のライフサイクルは終了します

デモ例

1)、カスタムBeanPostProcessor、コードは次のとおりです。

 

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * 自定义BeanPostProcessor
 *
 * @date 2019-12-24 11:23
 **/
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean,
                                                  String beanName) throws BeansException {
        System.out.println("BeanPostProcessor postProcessBeforeInitialization 方法被调用");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,
                                                 String beanName) throws BeansException {
        System.out.println("BeanPostProcessor postProcessAfterInitialization 方法被调用");
        return bean;
    }
}

2)、TestBeanエンティティクラス、コードは次のとおりです。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * 测试bean
 *
 * @date 2019-12-24 11:17
 **/
public class TestBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;

    public TestBean() {
        System.out.println("TestBean 构造方法被调用");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware 的 setBeanFactory 方法被调用");
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("BeanNameAware 的 setBeanName 方法被调用");
        this.beanName = name;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware 的 setApplicationContext 方法被调用");
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean 的 afterPropertiesSet 方法被调用");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean 的 destroy 方法被调用");
    }

    public void myInitMethod(){
        System.out.println("自定义的 myInitMethod 方法被调用");
    }

    public void myDestroyMethod(){
        System.out.println("自定义的 myDestroyMethod 方法被调用");
    }
}

3)テストコードは次のとおりです。

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * ApplicationContext测试
 *
 * @date 2019-12-24 11:31
 **/
public class ApplicationContextTest {
    public static void main(String[] args) {
        System.out.println("开始初始化ApplicationContext容器");
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application_context.xml");
        System.out.println("ApplicationContext容器初始化完毕");
        applicationContext.close();
    }
}

4)src / test / resources /application_context.xml構成ファイルの内容は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

	<!-- 自定义BeanPostProcessor -->
	<bean id="myBeanPostProcessor" class="com.springboot.demo.bean.MyBeanPostProcessor"/>

	<!-- 测试bean -->
	<bean id="testBean" class="com.springboot.demo.bean.TestBean" init-method="myInitMethod" 
		  destroy-method="myDestroyMethod"/>
</beans>

5)実行結果は次のとおりです。

开始初始化ApplicationContext容器
TestBean 构造方法被调用
BeanNameAware 的 setBeanName 方法被调用
BeanFactoryAware 的 setBeanFactory 方法被调用
ApplicationContextAware 的 setApplicationContext 方法被调用
BeanPostProcessor postProcessBeforeInitialization 方法被调用
InitializingBean 的 afterPropertiesSet 方法被调用
自定义的 myInitMethod 方法被调用
BeanPostProcessor postProcessAfterInitialization 方法被调用
ApplicationContext容器初始化完毕
DisposableBean 的 destroy 方法被调用
自定义的 myDestroyMethod 方法被调用

実行結果から、ApplicationContextBeanのライフサイクル図のプロセスと一致していることがわかります。

3、BeanFactoryBeanのライフサイクル

BeanFactoryBeanのライフサイクル図は次のとおりです。

上の図からわかるように、BeanFactoryBeanのライフサイクルとApplicationContextBeanのライフサイクルステップは基本的に同じです。ここでは類似点は繰り返さず、以下では相違点のみを分析します。

1)BeanFactoryコンテナーは、ApplicationContextAwareインターフェースのsetApplicationContextメソッドを呼び出しません。

2)BeanPostProcessorインターフェイスのpostProcessBeforeInitialzationメソッドとpostProcessAfterInitializationメソッドは、BeanPostProcessorがxmlで構成されていても自動的に呼び出されないため、コードを使用して手動で登録する必要があります。

3)BeanFactoryコンテナーが開始されるとスコープがシングルトンで遅延ロードされていないすべてのBeanを含め、すべてのBeanがインスタンス化されるわけではありませんが、呼び出されたときにのみインスタンス化されます(getBeanメソッド呼び出し)

デモ例

以下に示すように、カスタムBeanPostProcessor、TestBean、および構成ファイルの内容はすべて変更されておらず、テストクラスのみが変更されています。

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

import com.springboot.demo.bean.MyBeanPostProcessor;

/**
 * BeanFactory测试
 *
 * @date 2019-12-24 14:17
 **/
public class BeanFactoryTest {
    public static void main(String[] args) {
        System.out.println("开始初始化BeanFactory容器");
        ConfigurableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("application_context.xml"));
        System.out.println("BeanFactory容器初始化完毕");
        // 这里必须手动注册 BeanPostProcessor
        beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());
        // 必须调用 BeanFactory 的 getBean 方法,不然 bean 是不会实例化的,因为 BeanFactory 中的 bean 都是懒加载
        beanFactory.getBean("testBean");
        beanFactory.destroySingletons();
    }
}

操作の結果は次のとおりです。

开始初始化BeanFactory容器
BeanFactory容器初始化完毕
TestBean 构造方法被调用
BeanNameAware 的 setBeanName 方法被调用
BeanFactoryAware 的 setBeanFactory 方法被调用
BeanPostProcessor postProcessBeforeInitialization 方法被调用
InitializingBean 的 afterPropertiesSet 方法被调用
自定义的 myInitMethod 方法被调用
BeanPostProcessor postProcessAfterInitialization 方法被调用
DisposableBean 的 destroy 方法被调用
自定义的 myDestroyMethod 方法被调用

実行結果から、BeanFactoryBeanのライフサイクル図のプロセスと一致していることがわかります。

4、まとめ

Beanのライフサイクル管理には、ApplicationContextとBeanFactoryがあります。Springでは、ApplicationContextメソッドを使用してBeanを取得することをお勧めします。BeanFactoryメソッドはSpringによって廃止されました。BeanFactoryメソッドを使用してBeanを取得することはお勧めしません。

参照:

https://www.jianshu.com/p/3944792a5fff

https://www.zhihu.com/question/38597960

おすすめ

転載: blog.csdn.net/ywlmsm1224811/article/details/103669833