このBaiduインタビューの質問を理解してください:春のBeanのライフサイクル

序文

実は面接の質問です。百度に面接したときに聞いたのですが、当時は(本当に上手だったので)答えませんでした。後でインターネットで答えを探して混乱しました。 「実際に」では、Beanのライフサイクルの一般的な説明がありますが、コード分析がないため、インターネットにアクセスして自分で情報を見つけました。Beanのライフサイクルを理解する必要があります。

インターネット上のほとんどのBeanは、インタビューのライフサイクルで検証されます。実際、JDKを参照すると、完全なBeanライフサイクルがあります。これにより、本が一方的なものであることが検証されます。最も新鮮な情報は、元のJDKを参照してください!!!

1.Beanの完全なライフサイクル

従来のJavaアプリケーションでは、Beanのライフサイクルは非常に単純です。Javaキーワードnewを使用してBeanをインスタンス化すると、Beanを使用できるようになります。Beanが使用されなくなると、Javaによって自動的にガベージコレクションされます。

対照的に、Spring管理Beanのライフサイクルははるかに複雑です。SpringによるBeanの管理は非常に拡張可能であるため、Beanのライフサイクルを正しく理解することが非常に重要です。以下に、Beanの構築プロセスを示します。

このBaiduインタビューの質問を理解してください:春のBeanのライフサイクル

上の図に示すように、Beanのライフサイクルは非常に複雑です。次の図の各ステップについて説明しましょう。

  1. Springが開始し、Springで管理する必要のあるBeanを検索してロードし、Beanをインスタンス化します。
  2. Beanがインスタンス化された後、Beanの導入と値がBeanの属性に注入されます
  3. BeanがBeanNameAwareインターフェースを実装している場合、SpringはBeanのIDをsetBeanName()メソッドに渡します。
  4. BeanがBeanFactoryAwareインターフェースを実装している場合、SpringはsetBeanFactory()メソッドを呼び出してBeanFactoryコンテナーインスタンスを渡します。
  5. BeanがApplicationContextAwareインターフェースを実装している場合、SpringはBeanのsetApplicationContext()メソッドを呼び出し、Beanが配置されているアプリケーションコンテキスト参照を渡します。
  6. BeanがBeanPostProcessorインターフェースを実装している場合、SpringはpostProcessBeforeInitialization()メソッドを呼び出します。
  7. BeanがInitializingBeanインターフェースを実装している場合、SpringはafterPropertiesSet()メソッドを呼び出します。同様に、Beanがinit-methodを使用して初期化メソッドを宣言する場合、メソッドも呼び出されます
  8. BeanがBeanPostProcessorインターフェースを実装している場合、SpringはpostProcessAfterInitialization()メソッドを呼び出します。
  9. この時点で、Beanはアプリケーションで使用できるようになります。それらは、アプリケーションコンテキストが破棄されるまで、アプリケーションコンテキストにとどまります。
  10. BeanがDisposableBeanインターフェースを実装している場合、Springはそのdestroy()インターフェースメソッドを呼び出します。同様に、Beanがdestroy-method宣言メソッドを使用している場合、このメソッドも呼び出されます。

上記は、SpringにおけるBeanのコアインターフェイスとライフサイクルです。上記のプロセスに答えるインタビューで十分です。ただし、JavaDocドキュメントを見ると、上記のインターフェイスに加えて、初期化プロセスに関係する他のインターフェイスがあります。

org.springframework.beans.factory.BeanFactoryから抜粋した、関連するすべてのインターフェースは次のとおりです。上記の既存のインターフェースを強調表示する必要はありません。追加の関連するインターフェースを以下に強調表示します。

このBaiduインタビューの質問を理解してください:春のBeanのライフサイクル

Beanの完全なライフサイクル

テキストは次のように説明されています。

------------初期化------------

  • BeanNameAware.setBeanName()は、このBeanを作成したBeanファクトリでBeanの名前を設定し、通常のプロパティ設定の後に呼び出され、InitializinngBean.afterPropertiesSet()メソッドの前に呼び出されます。
  • BeanClassLoaderAware.setBeanClassLoader():通常のプロパティが設定された後、InitializingBean.afterPropertiesSet()の前に呼び出されます
  • BeanFactoryAware.setBeanFactory():コールバックは、独自のBeanインスタンスファクトリを提供します。これは、通常のプロパティ設定の後、InitializingBean.afterPropertiesSet()またはカスタム初期化メソッドの前に呼び出されます。
  • EnvironmentAware.setEnvironment():コンポーネントの使用中に呼び出される環境を設定します
  • EmbeddedValueResolverAware.setEmbeddedValueResolver():StringValueResolverを設定して、埋め込み値の範囲の問題を解決します
  • ResourceLoaderAware.setResourceLoader():通常のBeanオブジェクトの後、afterPropertiesSetまたはカスタムinitメソッドの前、およびApplicationContextAwareの前に呼び出されます。
  • ApplicationEventPublisherAware.setApplicationEventPublisher():通常のBeanプロパティの後、初期化の前に、afterPropertiesSetまたはカスタム初期化メソッドを呼び出します。ApplicationContextAwareの前に呼び出されます。
  • MessageSourceAware.setMessageSource():通常のBeanプロパティの後、afterPropertiesSetまたはカスタム初期化メソッドを初期化する前、およびApplicationContextAwareの前に呼び出されます。
  • ApplicationContextAware.setApplicationContext():通常のBeanオブジェクトが生成された後、InitializingBean.afterPropertiesSetを呼び出す前、またはユーザー定義の初期化メソッドの前に呼び出されます。ResourceLoaderAware.setResourceLoader、ApplicationEventPublisherAware.setApplicationEventPublisher、MessageSourceAwareの後に呼び出されます。
  • ServletContextAware.setServletContext():実行時にServletContextを設定し、通常のBeanの初期化後に呼び出し、InitializingBean.afterPropertiesSetの前に呼び出し、ApplicationContextAwareの後に呼び出します 注:WebApplicationContextが実行されているときです。
  • BeanPostProcessor.postProcessBeforeInitialization():このBeanPostProcessorは、指定された新しいBeanインスタンスに適用され、Bean初期化コールバックメソッド(InitializingBean.afterPropertiesSetやカスタム初期化メソッドなど)の前に呼び出されます。このBeanは、プロパティの値を設定する準備ができています。返されるBeanの例は通常のオブジェクトでラップされ、デフォルトの実装はBeanを返します。
  • BeanPostProcessor.postProcessAfterInitialization():このBeanPostProcessorは、指定された新しいBeanインスタンスに適用され、Bean初期化コールバックメソッド(InitializingBean.afterPropertiesSetやカスタム初期化メソッドなど)の後に呼び出されます。このBeanは、プロパティの値を設定する準備ができています。返されたBeanの例は、通常のオブジェクトでラップされている可能性があります
  • InitializingBean.afterPropertiesSet():すべてのBeanプロパティを設定した後にBeanFactoryによって呼び出されます(そしてBeanFactoryとApplicationContextAwareを満たします)。

- - - - - - 破壊 - - - - - -

BeanFactoryが閉じられると、Beanのライフサイクルは次のメソッドを呼び出します。

DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()

次に、Beanのライフサイクル検証

Beanのライフサイクルプロセスを検証するために、2つの形式があります。1つはインタビュー用に準備され、もう1つはプロセス全体を理解するために準備されています。以下のコードを見てみましょう。

  • Book.class
public class Book implements BeanNameAware,BeanFactoryAware,
        ApplicationContextAware,InitializingBean,DisposableBean {

    private String bookName;
    public Book(){
        System.out.println("Book Initializing ");
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Book.setBeanFactory invoke");
    }

    public void setBeanName(String name) {
        System.out.println("Book.setBeanName invoke");
    }

    public void destroy() throws Exception {
        System.out.println("Book.destory invoke");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("Book.afterPropertiesSet invoke");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Book.setApplicationContext invoke");
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
        System.out.println("setBookName: Book name has set.");
    }

    public void myPostConstruct(){
        System.out.println("Book.myPostConstruct invoke");
    }

     // 自定义初始化方法
    @PostConstruct
    public void springPostConstruct(){
        System.out.println("@PostConstruct");
    }

    public void myPreDestory(){
        System.out.println("Book.myPreDestory invoke");
        System.out.println("---------------destroy-----------------");
    }

    // 自定义销毁方法
    @PreDestroy
    public void springPreDestory(){
        System.out.println("@PreDestory");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("------inside finalize-----");
    }
}
  • BeanPostProcessorを実装するMyBeanPostProcessorをカスタマイズします。
public class MyBeanPostProcessor implements BeanPostProcessor {

    // 容器加载的时候会加载一些其他的bean,会调用初始化前和初始化后方法
    // 这次只关注book(bean)的生命周期
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Book){
            System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Book){
            System.out.println("MyBeanPostProcessor.postProcessAfterInitialization");
        }
        return bean;
    }
}
  • resourcesディレクトリに新しいBean-Lifecycle.xmlを作成します
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  	<!-- 扫描bean -->
    <context:component-scan base-package="com.bean.lifecycle"/>

    <!-- 实现了用户自定义初始化和销毁方法 -->
    <bean id="book" class="com.bean.lifecycle.Book" init-method="myPostConstruct" destroy-method="myPreDestory">
      	<!-- 注入bean 属性名称 -->
        <property name="bookName" value="thingking in java" />
    </bean>

  	<!--引入自定义的BeanPostProcessor-->
    <bean class="com.bean.lifecycle.MyBeanPostProcessor"/>

</beans>
  • スタートアップクラスのテストを実行し、新しいSpringBeanLifecycleApplicationを作成します
public class SpringBeanLifecycleApplication {

    public static void main(String[] args) throws InterruptedException {
        // 为面试而准备的Bean生命周期加载过程
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
        Book book = (Book)context.getBean("book");
        System.out.println("Book name = " + book.getBookName());
        ((ClassPathXmlApplicationContext) context).destroy();

    }

}

テストを開始すると、出力結果は次のようになります。

ブック初期化setBookName:ブック名が設定されました。Book.setBeanName invoke Book.setBeanFactory invoke Book.setApplicationContext invoke MyBeanPostProcessor.postProcessBeforeInitialization @PostConstruct Book.afterPropertiesSet invoke Book.myPostConstruct invoke MyBeanPostProcessor.postProcessAfterInitialization Book name = thingsking in java

@PreDestory Book.destory invoke Book.myPreDestory invoke --------------- destroy -----------------

  • Beanの完全なライフサイクルを確認するには、Bookクラスを継承する新しいSubBookClassを作成する必要があります。
public class SubBookClass extends Book implements BeanClassLoaderAware,
        EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,
        ApplicationEventPublisherAware,MessageSourceAware{

    private String bookSystem;

    public String getBookSystem() {
        return bookSystem;
    }

    public void setBookSystem(String bookSystem) {
        System.out.println("设置BookSystem 的属性值");
        this.bookSystem = bookSystem;
    }

    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("SubBookClass.setBeanClassLoader() 方法被调用了");
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("SubBookClass.setApplicationEventPublisher() 方法被调用了");
    }

    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("SubBookClass.setEmbeddedValueResolver() 方法被调用了");
    }

    public void setEnvironment(Environment environment) {
        System.out.println("SubBookClass.setEnvironment() 方法被调用了");
    }

    public void setMessageSource(MessageSource messageSource) {
        System.out.println("SubBookClass.setMessageSource() 方法被调用了");
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("SubBookClass.setResourceLoader() 方法被调用了");
    }

}

上記のSubBookClassとBookは補完的です。

  • 新しいSubBean-Lifecycle.xmlを作成し、SubBookClassを挿入します
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="bookClass" class="com.bean.lifecycle.SubBookClass" init-method="myPostConstruct" destroy-method="myPreDestory">
        <property name="bookSystem" value="Java System" />
    </bean>

    <bean class="com.bean.lifecycle.MyBeanPostProcessor"/>

</beans>
  • 完全なSpringBeanLifecycleApplicationは次のとおりです。
public class SpringBeanLifecycleApplication {

    public static void main(String[] args) throws InterruptedException {
        // 为面试而准备的Bean生命周期加载过程
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
        Book book = (Book)context.getBean("book");
        System.out.println("Book name = " + book.getBookName());
        ((ClassPathXmlApplicationContext) context).destroy();

        // 完整的加载过程,当然了解的越多越好
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SubBean-Lifecycle.xml");
        SubBookClass subBookClass = (SubBookClass) applicationContext.getBean("bookClass");
        System.out.println("BookSystemName = " + subBookClass.getBookSystem());
        ((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();
    }

}

完全な結果を出力します。

ブック初期化setBookName:ブック名が設定されました。Book.setBeanName invoke Book.setBeanFactory invoke Book.setApplicationContext invoke MyBeanPostProcessor.postProcessBeforeInitialization @PostConstruct Book.afterPropertiesSet invoke Book.myPostConstruct invoke MyBeanPostProcessor.postProcessAfterInitialization Book name = thingking in java @PreDestory Book.destory invoke Book.myPreDestory invoke ------ - - - - -破壊 - - - - - - - - -

Book Initializingは、BookSystemのプロパティ値を設定します。Book.setBeanNameinvokeSubBookClass.setBeanClassLoader()メソッドはBook.setBeanFactoryを呼び出します。invokeSubBookClass.setEnvironment()メソッドはSubBookClass.setEmbeddedValueResolver()メソッドを呼び出します。SubBookClass.setResourceLoader()メソッドはSubBookClassと呼ばれます。 .setApplicationEventPublisher()メソッドが呼び出されます。SubBookClass.setMessageSource()メソッドが呼び出されます。Book.setApplicationContextinvokeMyBeanPostProcessor.postProcessBeforeInitializationBook.afterPropertiesSet invoke Book.myPostConstruct invoke MyBeanPostProcessor.postProcessAfterInitialization BookSystemName = Java System BookDestory invoke-myPreDestoryinvoke。---- - - - - - 破壊 - - - - - - - - -

おすすめ

転載: blog.csdn.net/doubututou/article/details/112618661