1. 程式人生 > >Spring註解驅動開發——bean的後置處理器

Spring註解驅動開發——bean的後置處理器

BeanPostProcessor:是一個介面,bean的後置處理器(實際是在bean的初始化前後執行操作)

public class MyBeanPostProcessor implements BeanPostProcessor{

	/**
	 * bean是容器呼叫構造器建立的例項
	 * beanName是例項的id
	 * 在所有初始化方法之前呼叫
	 */
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	
	/**
	 * bean是容器呼叫構造器建立的例項
	 * beanName是例項的id
	 * 在所有初始化方法之後呼叫
	 */
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

將MyBeanPostProcessor納入到容器中:

@Configuration
@Import(MyBeanPostProcessor.class)
public class LifeCycleConfig {

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

這樣該容器中的所有bean在初始化前後都會執行該後置處理器中的邏輯,即使未定義初始化方法這些邏輯也會執行的,由此可以猜測:BeanPostProcessor可能是面向切面的

通過檢視原始碼,整個邏輯是這樣的:

在呼叫構造器之後,會為物件的所有屬性賦值,賦值完成後會呼叫初始化方法,但是在呼叫初始化方法時會進入一個切面,完成在初始化的前後執行BeanPostProcessor的邏輯:容器會遍歷所有的BeanPostProcessor並依次執行每個後置處理器的前置方法(postProcessBeforeInitialization),直至全部執行完或者其中一個該類方法返回null,然後完成Bean的初始化,初始化完成後,容器會繼續遍歷執行所有的BeanPostProcessor的後置方法(postProcessAfterInitialization),直至全部執行完或者其中一個該方法返回null

JDK1.8之後interface也可以有方法體了,子類也可以不實現介面中已有方法體的方法:

public interface BeanPostProcessor {

	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

BeanPostProcessor在Spring底層的使用:

元件通過實現ApplicationContextAware介面獲取IOC容器,其實是ApplicationContextAwareProcessor在起作用

@Component
public class ContextBean implements ApplicationContextAware {

	private ApplicationContext context;

	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		context = applicationContext;
	}
}

怎麼獲取到的IOC容器呢?容器在呼叫Bean的構造器並給所有屬性賦值之後,在執行所有初始化方法之前和之後,會執行一些BeanPostProcessor介面的子類中的邏輯,比如ApplicationContextAwareProcessor,在執行ApplicationContextAwareProcessor的postProcessBeforeInitialization()方法時,會判斷Bean是否實現了ApplicationContextAware介面,然後注入相應的ApplicationContext容器給Bean使用

②對元件的屬性進行校驗的BeanValidationPostProcessor

InitDestroyAnnotationBeanPostProcessor:掃描Bean中標註了@PostConstruct和@PreDestroy註解的方法並執行,這也就是為什麼@PostConstruct標註的初始化方法在其他初始化方法之前執行

AutowiredAnnotationBeanPostProcessor:為bean中標註了@Autowired註解的屬性賦值,這就是為什麼可以在init()方法中使用@Autowired註解的屬性的原因,因為在呼叫init方法之前會將這些屬性的值注入

⑤AsyncAnnotationBeanPostProcessor:使標註了@Async的方法非同步執行