Verstehe diese Frage aus dem Baidu-Interview: den Lebenszyklus von Bean im Frühling

Vorwort

Dies ist eigentlich eine Interviewfrage. Ich wurde gefragt, als ich Baidu interviewte. Ich habe sie damals nicht beantwortet (weil ich wirklich gut darin war). Später suchte ich im Internet nach der Antwort und war verwirrt, als ich sah es. "In Aktion" gibt es eine allgemeine Erklärung des Bean-Lebenszyklus, aber es gibt keine Code-Analyse, also bin ich online gegangen, um die Informationen selbst zu finden, und wir müssen den Bean-Lebenszyklus verstehen!

Die meisten Bohnen im Internet werden im Lebenszyklus des Interviews überprüft. Tatsächlich gibt es einen vollständigen Bohnen-Lebenszyklus, wenn das JDK konsultiert wird. Dies bestätigt auch, dass das Buch einseitig ist. Die aktuellsten Informationen sind zu konsultieren Sie das Original JDK !!!

1. Der vollständige Lebenszyklus von Bean

In herkömmlichen Java-Anwendungen ist der Lebenszyklus einer Bean sehr einfach. Verwenden Sie das Java-Schlüsselwort new, um die Bean zu instanziieren, und dann kann die Bean verwendet werden. Sobald die Bean nicht mehr verwendet wird, wird sie automatisch von Java gesammelt.

Im Gegensatz dazu ist der Lebenszyklus von Spring Management Beans viel komplizierter. Es ist sehr wichtig, den Lebenszyklus von Beans richtig zu verstehen, da das Spring Management von Beans sehr erweiterbar ist. Das Folgende zeigt den Bauprozess einer Bean

Verstehe diese Frage aus dem Baidu-Interview: den Lebenszyklus von Bean im Frühling

Wie in der obigen Abbildung gezeigt, ist der Lebenszyklus von Bean ziemlich kompliziert. Beschreiben wir jeden Schritt in der folgenden Abbildung:

  1. Spring startet, findet und lädt Bohnen, die von Spring verwaltet werden müssen, und instanziiert die Bohnen
  2. Nachdem die Bohne instanziiert wurde, werden die Einführung und der Wert der Bohne in die Attribute der Bohne injiziert
  3. Wenn die Bean die BeanNameAware-Schnittstelle implementiert, übergibt Spring die Bean-ID an die setBeanName () -Methode
  4. Wenn die Bean die BeanFactoryAware-Schnittstelle implementiert, ruft Spring die setBeanFactory () -Methode auf, um die BeanFactory-Containerinstanz zu übergeben
  5. Wenn die Bean die ApplicationContextAware-Schnittstelle implementiert, ruft Spring die setApplicationContext () -Methode der Bean auf und übergibt die Anwendungskontextreferenz, in der sich die Bean befindet
  6. Wenn die Bean die BeanPostProcessor-Schnittstelle implementiert, ruft Spring ihre postProcessBeforeInitialization () -Methode auf.
  7. Wenn die Bean die InitializingBean-Schnittstelle implementiert, ruft Spring ihre afterPropertiesSet () -Methode auf. Wenn die Bean die Initialisierungsmethode mit der init-Methode deklariert, wird die Methode ebenfalls aufgerufen
  8. Wenn die Bean die BeanPostProcessor-Schnittstelle implementiert, ruft Spring ihre postProcessAfterInitialization () -Methode auf.
  9. Zu diesem Zeitpunkt kann die Bean von der Anwendung verwendet werden. Sie bleiben im Anwendungskontext, bis der Anwendungskontext zerstört wird.
  10. Wenn die Bean die DisposableBean-Schnittstelle implementiert, ruft Spring ihre destroy () -Schnittstellenmethode auf. Wenn die Bean die Deklarationsmethode destroy-method verwendet, wird diese Methode ebenfalls aufgerufen.

Das Obige ist die Kernschnittstelle und der Lebenszyklus von Bean im Frühjahr. Das Interview, das den obigen Prozess beantwortet, reicht aus. Beim Durchsuchen des JavaDoc-Dokuments sind neben der obigen Schnittstelle noch weitere Schnittstellen am Initialisierungsprozess beteiligt:

Aus org.springframework.beans.factory.BeanFactory werden alle zugehörigen Schnittstellen wie folgt angezeigt. Die oben genannten vorhandenen müssen nicht hervorgehoben werden, und die zusätzlichen zugehörigen Schnittstellen werden unten hervorgehoben

Verstehe diese Frage aus dem Baidu-Interview: den Lebenszyklus von Bean im Frühling

Bean vollständiger Lebenszyklus

Der Text wird wie folgt erklärt:

------------Initialisierung------------

  • BeanNameAware.setBeanName () legt den Namen der Bean in der Bean-Factory fest, die diese Bean erstellt hat. Sie wird nach der normalen Eigenschaftseinstellung und vor der InitializinngBean.afterPropertiesSet () -Methode aufgerufen
  • BeanClassLoaderAware.setBeanClassLoader (): Wird vor InitializingBean.afterPropertiesSet () aufgerufen, nachdem die normalen Eigenschaften festgelegt wurden
  • BeanFactoryAware.setBeanFactory (): Der Rückruf stellt eine eigene Bean-Instanzfactory bereit, die nach der normalen Eigenschaftseinstellung und vor InitializingBean.afterPropertiesSet () oder einer benutzerdefinierten Initialisierungsmethode aufgerufen wird
  • EnvironmentAware.setEnvironment (): Legen Sie fest, welche Umgebung aufgerufen werden soll, wenn die Komponente verwendet wird
  • EmbeddedValueResolverAware.setEmbeddedValueResolver (): Legen Sie StringValueResolver fest, um Probleme mit eingebetteten Wertebereichen zu lösen
  • ResourceLoaderAware.setResourceLoader (): Wird nach normalen Bean-Objekten, vor afterPropertiesSet oder einer benutzerdefinierten Init-Methode und vor ApplicationContextAware aufgerufen.
  • ApplicationEventPublisherAware.setApplicationEventPublisher (): Wird nach normalen Bean-Eigenschaften und vor der Initialisierung aufgerufen. Rufen Sie afterPropertiesSet oder eine benutzerdefinierte Initialisierungsmethode auf. Wird vor ApplicationContextAware aufgerufen.
  • MessageSourceAware.setMessageSource (): Wird nach normalen Bean-Eigenschaften, vor der Initialisierung nach AfterPropertiesSet oder benutzerdefinierten Initialisierungsmethoden und vor ApplicationContextAware aufgerufen.
  • ApplicationContextAware.setApplicationContext (): Wird aufgerufen, nachdem das normale Bean-Objekt generiert wurde, bevor InitializingBean.afterPropertiesSet oder die benutzerdefinierte Initialisierungsmethode aufgerufen wird. Wird aufgerufen nach ResourceLoaderAware.setResourceLoader, ApplicationEventPublisherAware.setApplicationEventPublisher, MessageSourceAware.
  • ServletContextAware.setServletContext (): Legen Sie ServletContext zur Laufzeit fest, rufen Sie es nach der normalen Bean-Initialisierung auf, rufen Sie es vor InitializingBean.afterPropertiesSet auf und rufen Sie es nach ApplicationContextAware auf.  Hinweis: Dies ist der Fall, wenn WebApplicationContext ausgeführt wird
  • BeanPostProcessor.postProcessBeforeInitialization (): Dieser BeanPostProcessor wird auf die angegebene neue Bean-Instanz angewendet und vor allen Rückrufmethoden für die Bean-Initialisierung aufgerufen (z. B. InitializingBean.afterPropertiesSet oder benutzerdefinierte Initialisierungsmethoden). Diese Bean ist bereit, den Wert der Eigenschaft zu füllen. Das zurückgegebene Bean-Beispiel kann von einem normalen Objekt umbrochen werden, und die Standardimplementierung gibt eine Bean zurück.
  • BeanPostProcessor.postProcessAfterInitialization (): Dieser BeanPostProcessor wird auf eine bestimmte neue Bean-Instanz angewendet und nach allen Rückrufmethoden für die Bean-Initialisierung (z. B. InitializingBean.afterPropertiesSet oder benutzerdefinierte Initialisierungsmethoden) aufgerufen. Diese Bean ist bereit, den Wert der Eigenschaft zu füllen. Das zurückgegebene Bean-Beispiel kann von gewöhnlichen Objekten umbrochen werden
  • InitializingBean.afterPropertiesSet (): Wird von BeanFactory aufgerufen, nachdem alle Bean-Eigenschaften festgelegt wurden (und BeanFactory und ApplicationContextAware erfüllen).

------------zerstören------------

Wenn die BeanFactory geschlossen ist, ruft der Lebenszyklus der Bean die folgenden Methoden auf:

DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()

Zweitens die Überprüfung des Lebenszyklus von Bean

Um den Bean-Lebenszyklusprozess zu überprüfen, gibt es zwei Formen: Eine ist für das Interview vorbereitet, die andere ist für das Verständnis des gesamten Prozesses vorbereitet. Schauen wir uns den folgenden Code an:

  • Buchklasse
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-----");
    }
}
  • Passen Sie MyBeanPostProcessor an, der BeanPostProcessor implementiert:
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;
    }
}
  • Erstellen Sie eine neue Bean-Lifecycle.xml im Ressourcenverzeichnis
<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>
  • Führen Sie einen Test der Startklasse durch und erstellen Sie eine neue 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();

    }

}

Starten Sie den Test und die Ausgabeergebnisse lauten wie folgt:

Buchinitialisierung setBookName: Der Buchname wurde festgelegt. Book.setBeanName ruft Book.setBeanFactory auf Book.setApplicationContext ruft MyBeanPostProcessor.postProcessBeforeInitialization @PostConstruct auf Book.afterPropertiesSet ruft Book.myPostConstruct auf und ruft MyBeanPostProcessor.postProcessAfterit auf

@PreDestory Book.destory ruft Book.myPreDestory auf --------------- destroy -----------------

  • Um den gesamten Lebenszyklus der Bean zu überprüfen, müssen Sie eine neue SubBookClass erstellen, um die Book-Klasse zu erben
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() 方法被调用了");
    }

}

Die oben genannten SubBookClass und Book ergänzen sich.

  • Erstellen Sie eine neue SubBean-Lifecycle.xml und fügen Sie SubBookClass ein
<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>
  • Die vollständige SpringBeanLifecycleApplication lautet wie folgt:
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();
    }

}

Geben Sie das vollständige Ergebnis aus:

Buchinitialisierung setBookName: Der Buchname wurde festgelegt. Book.setBeanName ruft Book.setBeanFactory auf. Book.setApplicationContext ruft MyBeanPostProcessor.postProcessBeforeInitialization @PostConstruct auf. Book.afterPropertiesSet ruft Book.myPostConstruct auf. Rufen Sie MyBeanPostProcessor auf. ---------zerstören-----------------

Durch die Buchinitialisierung wird der Eigenschaftswert von BookSystem festgelegt. Book.setBeanName ruft die SubBookClass.setBeanClassLoader () -Methode auf. Book.setBeanFactory ruft die SubBookClass.setEnvironment () -Methode auf. SubBookClass.setEmbeddedValueResolver () -Methode heißt SubBookClass.setResourceLoader Die Methode .setApplicationEventPublisher () wird aufgerufen. Die Methode SubBookClass.setMessageSource () wird aufgerufen. Book.setApplicationContext ruft MyBeanPostProcessor.postProcessBeforeInitialization Book.afterPropertiesSet auf. Rufen Sie Book.myPostConstruct auf. ----------zerstören-----------------

Ich denke du magst

Origin blog.csdn.net/doubututou/article/details/112618661
Empfohlen
Rangfolge