Spring註解驅動開發第16講——面試官再問你BeanPostProcessor的執行流程,就把這篇文章甩給他!

李阿昀發表於2020-12-01

寫在前面

在前面的文章中,我們講述了BeanPostProcessor的postProcessBeforeInitialization()方法和postProcessAfterInitialization()方法在bean初始化的前後呼叫。而且我們可以自定義類來實現BeanPostProcessor介面,並在postProcessBeforeInitialization()方法和postProcessAfterInitialization()方法中編寫我們自定義的邏輯。

今天,我們來一起探討下BeanPostProcessor的底層原理。

bean的初始化和銷燬

我們知道BeanPostProcessor的postProcessBeforeInitialization()方法是在bean的初始化之前被呼叫;而postProcessAfterInitialization()方法是在bean初始化的之後被呼叫。並且bean的初始化和銷燬方法我們可以通過如下方式進行指定。

(一)通過@Bean指定init-method和destroy-method

@Bean(initMethod="init", destroyMethod="destroy")
public Car car() {
    return new Car();
}

(二)通過讓bean實現InitializingBean和DisposableBean這倆介面

package com.meimeixia.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
public class Cat implements InitializingBean, DisposableBean {
	
	public Cat() {
		System.out.println("cat constructor...");
	}

	/**
	 * 會在容器關閉的時候進行呼叫
	 */
	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("cat destroy...");
	}

	/**
	 * 會在bean建立完成,並且屬性都賦好值以後進行呼叫
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("cat afterPropertiesSet...");
	}

}

(三)使用JSR-250規範裡面定義的@PostConstruct和@PreDestroy這倆註解

  • @PostConstruct:在bean建立完成並且屬性賦值完成之後,來執行初始化方法
  • @PreDestroy:在容器銷燬bean之前通知我們進行清理工作
package com.meimeixia.bean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.stereotype.Component;

/**
 *
 * @author liayun
 *
 */
@Component
public class Dog {

	public Dog() {
		System.out.println("dog constructor...");
	}
	
	// 在物件建立完成並且屬性賦值完成之後呼叫
	@PostConstruct
	public void init() {
		System.out.println("dog...@PostConstruct...");
	}
	
	// 在容器銷燬(移除)物件之前呼叫
	@PreDestroy
	public void destory() {
		System.out.println("dog...@PreDestroy...");
	}
	
}

(四)通過讓bean實現BeanPostProcessor介面

package com.meimeixia.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

/**
 * 後置處理器,在初始化前後進行處理工作
 * @author liayun
 *
 */
@Component // 將後置處理器加入到容器中,這樣的話,Spring就能讓它工作了
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessBeforeInitialization..." + beanName + "=>" + bean);
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessAfterInitialization..." + beanName + "=>" + bean);
		return bean;
	}

	@Override
	public int getOrder() {
		// TODO Auto-generated method stub
		return 3;
	}

}

通過以上這四種方式,我們就可以對bean的整個生命週期進行控制:

  • bean的例項化:呼叫bean的構造方法,我們可以在bean的無參構造方法中執行相應的邏輯。
  • bean的初始化:在初始化時,可以通過BeanPostProcessor的postProcessBeforeInitialization()方法和postProcessAfterInitialization()方法進行攔截,執行自定義的邏輯;通過@PostConstruct註解、InitializingBean和init-method來指定bean初始化前後執行的方法,在該方法中我們們可以執行自定義的邏輯。
  • bean的銷燬:可以通過@PreDestroy註解、DisposableBean和destroy-method來指定bean在銷燬前執行的方法,在該方法中我們們可以執行自定義的邏輯。

所以,通過上述四種方式,我們可以控制Spring中bean的整個生命週期。

相關文章