<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          源碼分享《SpringBean生命周期》

          共 14780字,需瀏覽 30分鐘

           ·

          2021-08-25 14:43

          今日主題:Spring Bean的生命周期的分析和說明

          使用場景:

          1.項目啟動做一些業(yè)務化的操作
          2.項目停止的時候做一些業(yè)務化的操作
          3.面試官會問你,SpringBena的生命周期了解嗎


          其實SpringBean的生命周期其實只有四個部分

          1. Bean的實例化

          2. Bean的初始化

          3. Bean的使用

          4. Bean的銷毀


          知識儲備

          接下來我們一起看幾個Spring提供的接口(源碼中的所有英文注釋全部留著了,大家可以看看Spring自身對其的描述,不同人可能會有不同的想法吧)

          1.BeanNameAware只有一個方法setBeanName,這個方法主要是讓Bean自身知道定義的Bean的名稱,有之前接觸過使用XML配置spring bean的同學,就應該知道,這個就是bean的id屬性;實現(xiàn)這個接口,我們的Bean就可以知道自身注冊在容器中的名稱

          public interface BeanNameAware extends Aware {
          /** * Set the name of the bean in the bean factory that created this bean. * <p>Invoked after population of normal bean properties but before an * init callback such as {@link InitializingBean#afterPropertiesSet()} * or a custom init-method. * @param name the name of the bean in the factory. * Note that this name is the actual bean name used in the factory, which may * differ from the originally specified name: in particular for inner bean * names, the actual bean name might have been made unique through appending * "#..." suffixes. Use the {@link BeanFactoryUtils#originalBeanName(String)} * method to extract the original bean name (without suffix), if desired. */ void setBeanName(String name);}


          2.BeanFactoryAware也是只有一個方法setBeanFactory,這個方法主要是讓Bean獲取到容器的內部信息,從而進行某些定制化的操作

          public interface BeanFactoryAware extends Aware {
          /** * Callback that supplies the owning factory to a bean instance. * <p>Invoked after the population of normal bean properties * but before an initialization callback such as * {@link InitializingBean#afterPropertiesSet()} or a custom init-method. * @param beanFactory owning BeanFactory (never {@code null}). * The bean can immediately call methods on the factory. * @throws BeansException in case of initialization errors * @see BeanInitializationException */ void setBeanFactory(BeanFactory beanFactory) throws BeansException;
          }


          3.ApplicationContextAware也是只有一個方法setApplicationContext,該方法可以將ApplicationContext設置到Bean中,可以由此獲取其他的bean。比如我們開發(fā)的時候,并不是說在每一個地方都能將屬性注入到我們想要的地方去的,比如在Utils使用到dao,我們就不能直接注入了,這個時候就是我們需要封裝springContext的時候了,而ApplicationContextAware就起了關鍵性的作用

          public interface ApplicationContextAware extends Aware {
          /** * Set the ApplicationContext that this object runs in. * Normally this call will be used to initialize the object. * <p>Invoked after population of normal bean properties but before an init callback such * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()} * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader}, * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and * {@link MessageSourceAware}, if applicable. * @param applicationContext the ApplicationContext object to be used by this object * @throws ApplicationContextException in case of context initialization errors * @throws BeansException if thrown by application context methods * @see org.springframework.beans.factory.BeanInitializationException */ void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
          }


          4.BeanPostProcessor從字面上來說,就是Bean的后置處理器,就是在bean的生命周期內,對Bean進行一系列的操作,簡單來說就是初始化之前操作Bean,初始化后在對于Bean進行操作

          public interface BeanPostProcessor {
          /** * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */ @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; }
          /** * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding {@code bean instanceof FactoryBean} checks. * <p>This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. * <p>The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean;????}}


          5.InitializingBean在當你通過sring容器生產(chǎn)出實現(xiàn)了該接口的類的實例后,它就會調用afterPropertiesSet方法,通過這個方法,你可以檢查你的bean是否正確地被初始化了

          public interface InitializingBean {
          /** * Invoked by the containing {@code BeanFactory} after it has set all bean properties * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc. * <p>This method allows the bean instance to perform validation of its overall * configuration and final initialization when all bean properties have been set. * @throws Exception in the event of misconfiguration (such as failure to set an * essential property) or if initialization fails for any other reason */ void afterPropertiesSet() throws Exception;
          }


          Spring Bean生命周期圖示

          062bc25fffd6f5e129e44a19b95e1e33.webp如圖所示

          1. Bean初期涉及到Bean定義和初始化加載,初始化加載部分,可以查看另一篇文章

          2. 實現(xiàn)接口BeanNameAware,BeanFactoryAware,ApplicationContextAware來在Bean中使用Spring框架的一些對象屬性。

          3. 實現(xiàn)接口BeanPostProcessor對于bean進行前置處理

          4. 調用bean的自定義方法(注解@PostConstruct方法)

          5. 實現(xiàn)InitializingBean方法

          6. Bean定義的初始化方法init-method

          7. 實現(xiàn)接口BeanPostProcessor對于bean進行后置處理

          8. 生存期.....

          9. 調用bean的自定義方法(注解PreDestory方法)

          10. 實現(xiàn)接口DisposableBean重寫destory方法

          11. Bean定義的銷毀方法destory-method


          額外知識點

          實現(xiàn)*Aware接口 在Bean中使用Spring框架的一些對象

          有些時候我們需要在Bean的初始化中使用Spring框架自身的一些對象來執(zhí)行一些操作,比如獲取ServletContext的一些參數(shù),獲取ApplicaitionContext中的BeanDefinition的名字,獲取Bean在容器中的名字等等。為了讓Bean可以獲取到框架自身的一些對象,Spring提供了一組名為*Aware的接口。
          這些接口均繼承于標記接口org.springframework.beans.factory.Aware,并提供一個將由Bean實現(xiàn)的set*方法,Spring通過基于setter的依賴注入方式使相應的對象可以被Bean使用
          就此我們來說一下重要的Aware接口

          • ApplicationContextAware: 獲得ApplicationContext對象,可以用來獲取所有Bean definition的名字。

          • BeanFactoryAware:獲得BeanFactory對象,可以用來檢測Bean的作用域。

          • BeanNameAware:獲得Bean在配置文件中定義的名字。

          • ResourceLoaderAware:獲得ResourceLoader對象,可以獲得classpath中某個文件。

          • ServletContextAware:在一個MVC應用中可以獲取ServletContext對象,可以讀取context中的參數(shù)。

          • ServletConfigAware在一個MVC應用中可以獲取ServletConfig對象,可以讀取config中的參數(shù)。

          代碼示例

          1.新建一個SpringBoot項目

          d22de1b7c6b907cb38fec04db01d7091.webp?

          2示例代碼如下:

          BeanLifeCycle.java

          package com.example.smile7up.demo.spring.bean;
          import com.example.smile7up.demo.spring.common.OrderCount;import org.springframework.beans.BeansException;import org.springframework.beans.factory.*;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;
          import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;
          /** * 2020/7/9 * * @author smile7up */public class BeanLifeCycle implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, ApplicationContextAware {

          public BeanLifeCycle() { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":調用Bean的構造器方法(constructor)"); }

          @Override public void setBeanName(String name) { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":獲取定義的Bean的名稱為:" + name);
          }
          @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":獲取定義的Bean所在的BeanFactory" + beanFactory.getClass().getSimpleName()); }

          @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":獲取定義的Bean所在的ApplicationContext,為" + applicationContext.getClass().getSimpleName()); }

          @PostConstruct public void postConstruct() { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":調用Bean的函數(shù):方法包含注解@PostConstruct"); }
          @Override public void afterPropertiesSet() throws Exception { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":調用Bean的函數(shù)實現(xiàn)接口InitializingBean,重寫方法afterPropertiesSet)"); }

          public void initMethod() { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":調用Bean的定義的時候聲明的initMethod"); }
          @PreDestroy public void preDestroy() { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":調用Bean的函數(shù):方法包含注解@PreDestroy"); }
          @Override public void destroy() throws Exception { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":調用Bean的函數(shù)實現(xiàn)接口DisposableBean,重寫方法destory"); }
          public void destroyMethod() { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement+":調用Bean的定義的時候聲明的destroyMethod)"); }}


          OrderCount.java

          package com.example.smile7up.demo.spring.common;
          import lombok.Getter;
          import java.util.concurrent.atomic.AtomicInteger;
          /** * 2020/7/9 * * @author smile7up */@Getterpublic class OrderCount {
          public static AtomicInteger count = new AtomicInteger(0);}


          BeanLifeCycleConfig.java

          package com.example.smile7up.demo.spring.config;
          import com.example.smile7up.demo.spring.bean.BeanLifeCycle;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
          /** * 2020/7/9 * * @author smile7up */@Configurationpublic class BeanLifeCycleConfig {
          @Bean(name = "testBeanName",initMethod = "initMethod", destroyMethod = "destroyMethod") public BeanLifeCycle beanLifeCycle() { return new BeanLifeCycle(); }}


          CustomBeanProcessor.java

          package com.example.smile7up.demo.spring.processor;
          import com.example.smile7up.demo.spring.bean.BeanLifeCycle;import com.example.smile7up.demo.spring.common.OrderCount;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.stereotype.Component;
          /** * 2020/7/9 * * @author smile7up */@Componentpublic class CustomBeanProcessor implements BeanPostProcessor {
          @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean.getClass() == BeanLifeCycle.class) { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement + ":調用方法postProcessBeforeInitialization..."); } return bean; }
          @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean.getClass() == BeanLifeCycle.class) { int andIncrement = OrderCount.count.getAndIncrement(); System.out.println(andIncrement + ":調用方法postProcessAfterInitialization..."); } return bean; }
          }


          執(zhí)行結果如下

          2020-07-15 14:13:36.988  INFO 20923 --- [           main] c.e.s.demo.spring.DemoSpringApplication  : Starting DemoSpringApplication on liuzuolongdeMacBook-Pro.local with PID 20923 (/Users/liuzuolong/project/smile_show_project/demo-spring/target/classes started by liuzuolong in /Users/liuzuolong/project/smile_show_project/demo-spring)2020-07-15 14:13:36.990  INFO 20923 --- [           main] c.e.s.demo.spring.DemoSpringApplication  : No active profile set, falling back to default profiles: default2020-07-15 14:13:37.741  INFO 20923 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)2020-07-15 14:13:37.758  INFO 20923 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]2020-07-15 14:13:37.758  INFO 20923 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.21]2020-07-15 14:13:37.821  INFO 20923 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext2020-07-15 14:13:37.822  INFO 20923 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 790 ms0:調用Bean的構造器方法(constructor)1:獲取定義的Bean的名稱為:testBeanName2:獲取定義的Bean所在的BeanFactoryDefaultListableBeanFactory3:獲取定義的Bean所在的ApplicationContext,為AnnotationConfigServletWebServerApplicationContext4:調用方法postProcessBeforeInitialization...5:調用Bean的函數(shù):方法包含注解@PostConstruct6:調用Bean的函數(shù)實現(xiàn)接口InitializingBean,重寫方法afterPropertiesSet)7:調用Bean的定義的時候聲明的initMethod8:調用方法postProcessAfterInitialization...2020-07-15 14:13:37.965  INFO 20923 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'2020-07-15 14:13:38.107  INFO 20923 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path ''2020-07-15 14:13:38.110  INFO 20923 --- [           main] c.e.s.demo.spring.DemoSpringApplication  : Started DemoSpringApplication in 1.42 seconds (JVM running for 2.479)Disconnected from the target VM, address: '127.0.0.1:64381', transport: 'socket'2020-07-15 14:13:42.260  INFO 20923 --- [       Thread-5] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'9:調用Bean的函數(shù):方法包含注解@PreDestroy10:調用Bean的函數(shù)實現(xiàn)接口DisposableBean,重寫方法destory11:調用Bean的定義的時候聲明的destroyMethod)


          經(jīng)過今天的學習,我們可以大致的了解了Spring Bean的生命周期,這樣對以后我們在寫技術代碼的時候,可以知道什么時候,實現(xiàn)什么方法,同樣也為我們后續(xù)的源碼分析研究打下基礎


          瀏覽 46
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  小香蕉网站 | 日本黄色大片免费看视频 | 国产3区在线观看 | se94se欧美setu升级 | 亚洲无码一本道 |