Spring中bean的生命周期詳解(面試說辭)


鏈接:https://blog.csdn.net/knknknkn8023/article/details/107130806/

Spring中bean的生命周期(詳解)

1.四個主要階段
2.常用的擴展點
3.影響多個bean的接口
4.只調用一次的接口
5.與aware有關的接口
6.兩個生命周期接口
7.總結:

四個主要階段

Spring bean的生命周期只有四個主要階段,其他都是在這四個主要階段前后的擴展點,這四個階段是:
1.實例化 Instantiation
2.屬性賦值 Populate
3.初始化 Initialization
4.銷毀 Destruction
其中實例化和屬性賦值分別對應構造方法和setter方法的注入,初始化和銷毀是用戶能自定義擴展的兩個階段。

可通過查源碼的方式發現,他們都在doCreate()方法中,

// 忽略了無關代碼
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (instanceWrapper == null) {
       // 實例化階段!
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
       // 屬性賦值階段!
      populateBean(beanName, mbd, instanceWrapper);
       // 初始化階段!
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }


   }

可以發現,分別調用三種方法:
1.createBeanInstance() -> 實例化
2.populateBean() -> 屬性賦值
3.initializeBean() -> 初始化
而銷毀階段是在容器關閉時調用的,在ConfigurableApplicationContext類的close()中

常用的擴展點

影響多個bean的接口

兩個最重要的接口:
InstantiationAwareBeanPostProcessor
BeanPostProcessor
實現這兩個接口的bean,會自動切入到相應的生命周期中,其中InstantiationAwareBeanPostProcessor是作用於實例化階段的前后,BeanPostProcessor是作用於初始化階段的前后。
具體代碼如圖:

package cn.xmx.ioc.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

import java.beans.PropertyDescriptor;

public class MyInstantiationAwareBeanPostProcessorAdapter extends InstantiationAwareBeanPostProcessorAdapter {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(beanName.equals("car")){
            System.out.println(beanName+"在實例化之前");
        }

        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }
    
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(beanName.equals("car")){
            System.out.println(beanName+"在實例化之后");
        }
        return super.postProcessAfterInstantiation(bean, beanName);
    }

}
package cn.xmx.ioc.lifecycle;

import java.lang.reflect.Proxy;

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


//后置處理器
public class NdBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       System.out.println("NdBeanPostProcessor 在"+beanName+"對象初始化之【前】調用......");
       if(beanName.equals("car")) {
           return   new CglibInterceptor().getIntance(bean.getClass());
       }
       return bean;
        
    }
    
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("NdBeanPostProcessor 在"+beanName+"對象初始化之【后】調用......");
        return bean;
    }

}
package cn.xmx.ioc.lifecycle;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MainConfig {
    @Bean(name="car",initMethod="init",destroyMethod="destroy")
    public Car getCar() {
        return new Car("大黃蜂");
    }
    

    @Bean
    public BeanPostProcessor getBeanPostProcessor() {
        return new NdBeanPostProcessor();
    }
    @Bean
    public InstantiationAwareBeanPostProcessorAdapter getIns(){
        return new MyInstantiationAwareBeanPostProcessorAdapter();
    }

}
package cn.xmx.ioc.lifecycle;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/*
 四個主生命周期
         (1)實例化之前干預     InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInstantiation()
     1.實例化
          (2)實例化之后干預   InstantiationAwareBeanPostProcessorAdapter.postProcessAfterInstantiation()
     2.填充屬性(給屬性賦值)
     

          (1)初始化之前干預   BeanPostProcessor.postProcessBeforeInitialization()
     3.初始化化(比如准備資源文件)
             3) 屬性進行干預  ----修改屬性或屬性值
     
         (2)初始化之后干預    BeanPostProcessor.postProcessAfterInitialization()
         
     4.銷毀(釋放資源---對象從內存銷毀)

 N個接口
     1、干預多次
         1)BeanPostProcessor
     2、干預一次
         1)Aware
     
 */
public class TestLifeCycle {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        Car car = (Car) context.getBean("car");
        System.out.println(car);//toString
        System.out.println("beanname:"+car.getBeanName());
        System.out.println("beanfactory:"+car.getBeanFactory());
        System.out.println("applicationContext:"+car.getApplicationContext());
    }
}

只調用一次的接口

與aware有關的接口

BeanNameAware
BeanFactoryAware
ApplicationContextAware
需要實體類實現這些接口,分別調用 Bean 的 setBeanName() 方法傳入當前 Bean 的 id 值,調用 setBeanFactory() 方法傳入當前工廠實例的引用,調用 setApplicationContext() 方法傳入當前 ApplicationContext 實例的引用。
具體代碼如下圖所示:

package cn.xmx.ioc.lifecycle;

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.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Car implements BeanNameAware, BeanFactoryAware, ApplicationContextAware {
    private String  name;
    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;
    public void init() {
        System.out.println("car 在初始化---加載資源");
        

    }
    
    public void destroy() {
        System.out.println("car 在銷毀---釋放資源");
    }


​    
​    

    public Car() {
        super();
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public Car(String name) {
        super();
        this.name = name;
        System.out.println("car實例化了");
    }


    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("beanFactory:"+beanFactory);
        this.beanFactory = beanFactory;
    }
    
    public BeanFactory getBeanFactory(){
        return this.beanFactory;
    }
    
    public void setBeanName(String s) {
        System.out.println("beanName:"+s);
        this.beanName = s ;
    }
    
    public String getBeanName() {
        return this.beanName;
    }
    
    public ApplicationContext getApplicationContext() {
        return this.applicationContext;
    }
    
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext:"+applicationContext);
        this.applicationContext = applicationContext;
    }

}

兩個生命周期接口

實例化和屬性賦值都是Spring幫助我們做的,能夠自己實現的有初始化和銷毀兩個生命周期階段。
1.InitializingBean 對應生命周期的初始化階段,在源碼的invokeInitMethods(beanName, wrappedBean, mbd);方法中調用。
2.DisposableBean 類似於InitializingBean,對應生命周期的銷毀階段,以ConfigurableApplicationContext#close()方法作為入口,實現是通過循環取所有實現了DisposableBean接口的Bean然后調用其destroy()方法 。

總結:

Bean 生命周期的整個執行過程描述如下:

1.如果創建了一個類繼承了InstantiationAwareBeanPostProcessorAdapter接口,並在配置文件中配置了該類的注入,即InstantiationAwareBeanPostProcessorAdapter和bean關聯,則Spring將調用該接口的postProcessBeforeInstantiation()方法。
2.根據配置情況調用 Bean 構造方法或工廠方法實例化 Bean。
3.如果InstantiationAwareBeanPostProcessorAdapter和bean關聯,則Spring將調用該接口的postProcessAfterInstantiation()方法。
4.利用依賴注入完成 Bean 中所有屬性值的配置注入。
5.如果 Bean 實現了 BeanNameAware 接口,則 Spring 調用 Bean 的 setBeanName() 方法傳入當前 Bean 的 id 值。
6.如果 Bean 實現了 BeanFactoryAware 接口,則 Spring 調用 setBeanFactory() 方法傳入當前工廠實例的引用。
7.如果 Bean 實現了 ApplicationContextAware 接口,則 Spring 調用 setApplicationContext() 方法傳入當前 ApplicationContext 實例的引用。
8.如果 BeanPostProcessor 和 Bean 關聯,則 Spring 將調用該接口的預初始化方法 postProcessBeforeInitialzation() 對 Bean 進行加工操作,此處非常重要,Spring 的 AOP 就是利用它實現的。
9.如果 Bean 實現了 InitializingBean 接口,則 Spring 將調用 afterPropertiesSet() 方法。
10.如果在配置文件中通過 init-method 屬性指定了初始化方法,則調用該初始化方法。
11.如果 BeanPostProcessor 和 Bean 關聯,則 Spring 將調用該接口的初始化方法 postProcessAfterInitialization()。
注意:以上工作完后才能以后就可以應用這個bean了,那這個bean是一個singleton的,所以一般這種情況下我們調用同一個id的bean會是在內容地址相同的實例,當然在spring配置文件中也可以配置非Singleton。
12.如果 Bean 實現了 DisposableBean 接口,則 Spring 會調用 destory() 方法將 Spring 中的 Bean 銷毀;如果在配置文件中通過 destory-method 屬性指定了 Bean 的銷毀方法,則 Spring 將調用該方法對 Bean 進行銷毀。


免責聲明!

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



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