【SpringBoot】SpringBoot的基礎,全面理解bean的生命周期


前言

前段時間直接上手使用springboot開發了一個數據平台的后台部分,但是自身對於springboot的原理和過程還不是很清晰,所以反過來學習下springboot的基礎。

大家都知道springboot是基於注解的,IOC和AOP是它的兩大重要特性,然后AOP又是基於IOC來實現的。那么弄懂IOC就很有必要了。

IOC:控制反轉,一種設計思想,它是Spring的核心。簡單點說就是spring管理bean的容器。IOC容器一般具備兩個基本功能:

  1、通過描述管理Bean,包括發布和獲取。

  2、描述Bean之間的依賴關系。這兩個問題深究下去是沒有邊界的,尤其是Bean之間的依賴關系,這個就是spring的核心。

從IOC的概念和功能就引申出了一個重要概念: Bean   

本文將全方位介紹Spring Bean的生命周期

 

Spring Bean的簡要流程:

 

 

 

如上圖所示,在XML或者其他文件定義bean之后,spring通過注解的方式將bean傳遞到IOC容器,IOC容器將bean注冊后給類class調用並實例化-構建,之后將bean放入到容器的緩沖池供程序調用。

從圖片可以看到Spring Bean 在整個SpringBoot 項目中至關重要,它經過的路徑如下:

  1. 實例化  【IOC容器尋找Bean的定義信息並將其實例化】
  2. 設置bean的Aware 【Aware意指能提前感知的,是spring的一個重要接口,使用依賴注入,spring按照Bean定義信息配置Bean的所有屬性】
  3. BeanPostProcessor.postProcessBeforeInitialization(Object bean, String beanName)   【如果BeanPostProcessor和Bean關聯,那么其postProcessBeforeInitialization()方法將被調用,Spring 框架會遍歷得到容器中所有的 BeanPostProcessor ,挨個執行】
  4. InitializingBean.afterPorpertiesSet     【初始化bean, springboot讀取properties文件的過程,默認的application.properties 還有其他方式】
  5. BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName)  【如果有BeanPostProcessor和Bean關聯,那么其postProcessAfterInitialization()方法將被調用】
  6. SmartInitializingSingleton.afterSingletonsInstantiated
  7. SmartLifecycle.start
  8. 運行Bean
  9. SmartLifecycle.stop(Runnable callback)     
  10. DisposableBean.destroy()     【銷毀】

 

詳細解釋

1.實例化對應代碼

  【使用合適的初始化方案來創建一個新的bean實例,factory-method,構造器注入或者簡單的直接實例化

  實例化策略類:
    InstantiationStrategy

  實例化具體方法:
    AbstractAutowireCapableBeanFactory.createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)

  

  構造器注入:

    @CompnentScan 【啟動類】查找beans,結合@Autowired構造注入【Service層】

  

  Factory Mothod方式也分兩種, 分別是靜態工廠方法 和 實例工廠方法。

   1. 先創建一個汽車car類 

public class Car {
    private int id;
    private String name;
    private int price;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getPrice() {
        return price;
    }
 
    public void setPrice(int price) {
        this.price = price;
    }
 
    @Override
    public String toString() {
        return "Car [id=" + id + ", name=" + name + ", price=" + price + "]";
    }
 
  public Car(){
 
  }
 
    public Car(int id, String name, int price) {
        super();
        this.id = id;
        this.name = name;
        this.price = price;
    }
}
View Code

      2. 定義一個工廠類 (定義了1個靜態的bean 容器map. 然后提供1個靜態方法根據Car 的id 來獲取容器里的car對象。)

import java.util.HashMap;
import java.util.Map;
 
public class CarStaticFactory {
    private static Map<Integer, Car> map = new HashMap<Integer,Car>();
 
    static{
        map.put(1, new Car(1,"Honda",300000));
        map.put(2, new Car(2,"Audi",440000));
        map.put(3, new Car(3,"BMW",540000));
    }
 
    public static Car getCar(int id){
        return map.get(id);
    }

}
View Code

           3. 定義配置XML (利用靜態工廠方法定義的bean item種, class屬性不在是bean的全類名, 而是靜態工廠的全類名, 而且還需要指定工廠里的getBean 靜態方法名字和參數)

  <!-- 
        Static Factory method:
        class: the class of Factory
        factory-method: method of get Bean Object
        constructor-arg: parameters of factory-method
     -->
    <bean id="bmwCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
        <constructor-arg value="3"></constructor-arg>           
    </bean>
 
    <bean id="audiCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
        <constructor-arg value="2"></constructor-arg>           
</bean>

     4. 客戶端調用factory-method的bean 

public static void h(){
  ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factoryMethod.xml");
  Car car1 = (Car) ctx.getBean("bmwCar");
  System.out.println(car1);
 
  car1 = (Car) ctx.getBean("audiCar");
  System.out.println(car1);
}

 

  

2.設置bean的Aware

  【InitializingBean.afterPorpertiesSet,BeanPostProcessor對bean的加工處理基本上在一塊出現。】

  設置Aware方法順序:

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware

  BeanPostProcessor.postProcessBeforeInitialization

 

  ApplicationContextAwareProcessor也會設置Aware:

  • EnvironmentAware
  • EmbeddedValueResolverAware
  • ResourceLoaderAware
  • ApplicationEventPublisherAware
  • MessageSourceAware
  • ApplicationContextAware

調用afterpropertiesSet方法:位於AbstractAutowireCapableBeanFactory.invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)方法中

源碼:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        
      // 設置Aware  
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }
        
      //BeanPostProcessor的postProcessBeforeInitialization  
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
           //調用init方法,其判斷是否是InitializingBean的實例,然后調用afterPropertiesSet
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
    
      //BeanPostProcessor的postProcessAfterInitialization  
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }
View Code

 

3. SmartInitializingSingleton.afterSingletonsInstantiated的調用位置

  【DefaultListableBeanFactory.preInstantiateSingletons方法,其在所有的bean都實例化完成之后調用】
 
  源碼:
@Override
    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        // 觸發實例化所有的非懶加載的單例
        for (String beanName : beanNames) {
           ...
        }

        // Trigger post-initialization callback for all applicable beans...
        // 觸發應用bean的post-initialization回調,也就是afterSingletonsInstantiated方法
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged(new PrivilegedAction<Object>() {
                        @Override
                        public Object run() {
                            smartSingleton.afterSingletonsInstantiated();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }
View Code

4. SmartLifecycle.start

  在ApplicationContext結束刷新finishRefresh時,getLifecycleProcessor().onRefresh();

  判斷bean是否為SmartLifecycle並且autoStartup。

  位於:
  DefaultLifecycleProcessor.onRefresh

5. stop方法

  在Application.close的時候,調用getLifecycleProcessor().stop()方法仍然在DefaultLifecycleProcessor內部

6. DisposableBean.destroy方法

  doCreateBean方法中會判斷bean是否有銷毀相關操作,實現了DisposableBean方法或定義了銷毀方法。

  AbstractAutowireCapableBeanFactory.doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

7. Bean 生命周期演示代碼以及運行結果

public class HelloWorld implements SmartInitializingSingleton,SmartLifecycle,InitializingBean,
        DisposableBean,MyInterface,BeanNameAware,ApplicationContextAware
{

    private final Log logger = LogFactory.getLog(getClass());
    private boolean isRunning;
    

    public HelloWorld() {
        System.out.println("實例化");
    }

    public void sayHello(){
        System.out.println("hello World");
    }

    public void afterSingletonsInstantiated() {
        System.out.println("SmartInitializingSingleton afterSingletonsInstantiated");
    }

    public void start() {
        isRunning = true;
        System.out.println("LifeCycle start");
    }

    public void stop() {
        System.out.println("LifeCycle stop");
    }

    public boolean isRunning() {
        return isRunning;
    }

    public boolean isAutoStartup() {
        return true;
    }

    public void stop(Runnable callback) {
        System.out.println("LifeScycle stop");
        callback.run();
    }

    public int getPhase() {
        return 0;
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("afterproperties set");
    }

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

    public void my(String str) {
        System.out.println(str);
    }

    public void setBeanName(String name) {
        System.out.println("set bean Name aware");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("set Application Aware");
    }
}


//MyInterface接口
public interface MyInterface {
    void my(String str);
}


//app.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="porcessor" class="me.aihe.MyBeanPostProcessor" />
    <bean id="hello" class="me.aihe.HelloWorld">

    </bean>
</beans>



//SpringApp
public class SpringApp {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
        HelloWorld hello = (HelloWorld) applicationContext.getBean("hello");
        hello.sayHello();
        applicationContext.close();
    }
}
View Code

 

 

總結:

Spring Bean  是整個Spring的基石,意義不言而喻,通過bean可以獲取對象,實現容器,反射,簡化配置,中間件,線程池等等。所以學習它非常有必要。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM