BeanProcessor的理解java
BeanProcessor是spring中的一個重要接口,他有兩個接口方法一個是postProcessBeforeInitialization
前置初始化,另外一個是postProcessAfterInitialization
後置初始化。從名稱上就能夠大概清楚這個接口的做用:在一個業務流程的先後加入兩個接口方法,當執行這個業務流程時,就會觸發這兩個接口方法的執行。簡單的總結一下有兩個要點:spring
而在spring中,就有不少實現了BeanProcessor的bean,經過在重要的業務流程(如bean的生命週期流程)的先後加上BeanProcessor接口方法,就能夠對業務邏輯進行修改或補充。api
一個BeanProcessor的使用實例數組
在spring的bean生命週期中,BeanProcessor接口方法會在bean建立後的初始化方法(init-method或@PostConstruct指向的方法)先後執行before
和after
方法;那有沒有在bean建立先後執行的接口方法呢?答案是確定有的,這個功能是由BeanProcessor的子接口InstantiationAwareBeanPostProcessor
來實現的,他也是有before
和after
方法,會在bean實例化先後執行。緩存
咱們先定義一個BeanProcessor
接口實現類和一個InstantiationAwareBeanPostProcessor
接口實現類。app
BeanPostProcessor
實現類:ide
//net.postProcessor.CustomerPostProcessor
@Component
public class CustomerPostProcessor implements BeanPostProcessor {
@PostConstruct
public void init(){
System.out.println("執行CustomerPostProcessor的PostConstruct");
}
public CustomerPostProcessor(){
System.out.println("執行CustomerPostProcessor的構造方法");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean+"======BeforeInitialization======"+ beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean+"======AfterInitialization======"+ beanName);
return bean;
}
}
複製代碼
InstantiationAwareBeanPostProcessor
實現類:post
//net.postProcessor.CustomerInitialPostProcessor
@Component
public class CustomerInitialPostProcessor implements InstantiationAwareBeanPostProcessor {
@PostConstruct
public void init(){
System.out.println("執行CustomerInitialPostProcessor的PostConstruct");
}
public CustomerInitialPostProcessor(){
System.out.println("執行CustomerInitialPostProcessor的構造方法");
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("bean初始化前執行:class爲"+beanClass.getName()+"|beanName爲"+beanName);
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("bean初始化後執行:Object爲"+bean+"|beanName爲"+beanName);
return false;
}
}
複製代碼
再建立一個普通的bean對象:this
//net.postProcessor.FirstBean
@Component
public class FirstBean implements InitializingBean {
private String msg = "hello";
@PostConstruct
public void init(){
System.out.println("執行FirstBean的PostConstruct");
}
public FirstBean(){
System.out.println("FirstBean構造方法!"+msg);
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("執行FirstBean的afterPropertiesSet");
}
}
複製代碼
咱們建立一個spring工廠對象將上述bean加載進去:spa
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("net.postProcessor");
}
//執行獲得如下結果:
執行CustomerInitialPostProcessor的構造方法
執行CustomerInitialPostProcessor的PostConstruct
執行CustomerPostProcessor的構造方法
執行CustomerPostProcessor的PostConstruct
bean初始化前執行:class爲net.postProcessor.FirstBean|beanName爲firstBean FirstBean構造方法!hello bean初始化後執行:Object爲net.postProcessor.FirstBean@79179359|beanName爲firstBean net.postProcessor.FirstBean@79179359======BeforeInitialization======firstBean
執行FirstBean的PostConstruct
執行FirstBean的afterPropertiesSet
net.postProcessor.FirstBean@79179359======AfterInitialization======firstBean
複製代碼
經過上述結果證實了咱們以前的說法是正確的:
1.BeanPostProcessor接口類會優先實例化,且在實例化中沒法不會調用BeanPostProcessor接口方法的
2.InstantiationAwareBeanPostProcessor接口方法會在FirstBean構造方法構造方法先後執行
3.BeanPostProcessor接口方法會在FirstBean實例化後進行初始化的先後執行
注意:若@PostConstruct註解方法方法未執行,請加入javax.annotation:javax.annotation-api:1.3.2
jar包依賴,緣由是@PostConstruct是J2EE標準的註解,不是spring本身的接口,而在JDK8往上的版本中設計者打算棄用這些註解,因此作了處理,咱們是沒有辦法直接使用J2EE標準註解的(@Resource、@PostConstruct、@PreDestroy等幾個註解),爲了兼容這種狀況,因此有了javax.annotation-api
jar包的產生(或者下降JDK版本)。
BeanProcessor大概的實現思路
經過以前的瞭解BeanProcessor的使用,咱們能夠知道BeanProcessor並不複雜,可是卻十分的重要,下面來分析下BeanProcessor的實現思路:
建立個接口A,接口包含一些切點方法(Before、After、Around之類的),實現這個接口A的類要在使用前就建立好
咱們須要有個業務流程,這個業務流程由若干步組成;將接口A的接口方法插入到這些業務步驟之間(須要擴展的地方)
要執行這個業務流程時,把接口A的實現類對象賦值到業務流程中,在執行業務流程中,就會觸發接口方法的執行完成功能擴展
當咱們更換賦值到業務流程中的接口A的實現類時,對應的擴展邏輯也會隨之變化,這樣就實現了可插拔式的擴展邏輯(策略模式)。
一個BeanProcessor的簡化邏輯實例
在spring中咱們能夠建立任意數量的bean實現BeanProcessor接口,因此實際上咱們是要一個全局的beanProcessorList
對象用來存儲這些BeanProcessor對象;在執行業務代碼時,要循環這個beanProcessorList
對象,獲取你須要的BeanProcessor對象來執行接口方法。下面是一個模擬spring bean生命週期的簡化版,來幫助你理解spring中BeanProcessor的工做原理。
net.postProcessor.SecondBean.java
@Component
public class SecondBean {
private String msg = "world";
public SecondBean(){
System.out.println("SecondBean構造方法!"+msg);
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
複製代碼
net.postProcessor.CustomerPostProcessor.java
@Component
public class CustomerPostProcessor implements BeanPostProcessor {
@PostConstruct
public void init(){
System.out.println("執行CustomerPostProcessor的PostConstruct");
}
public CustomerPostProcessor(){
System.out.println("執行CustomerPostProcessor的構造方法");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean+"======BeforeInitialization======"+ beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean+"======AfterInitialization======"+ beanName);
return bean;
}
}
複製代碼
net.postProcessor.PostProcessor.java
public class PostProcessor {
//模擬掃描到的bean信息<"SecondBean", "net.postProcessor.SecondBean">
Map<String, String> scanBeanMap = new HashMap<>();
//模擬spring的beanPostProcessors列表
List<BeanPostProcessor> processorBeanList = new ArrayList<>();
//模擬bean對象緩存
Map<String, Object> beanCache = new HashMap<>();
//添加掃描的bean信息
public PostProcessor addBeanInfo(String beanName, String classPath){
this.scanBeanMap.put(beanName, classPath);
return this;
}
//模擬bean建立流程
public Object execute(){
try {
//先臨時存儲實現了postProcessor接口的bean對象
List<BeanPostProcessor> postProcessorStrList = new ArrayList<>();
//循環scanBeanMap,獲取bean列表中實現了postProcessor接口的類,加入processorBeanList中
for(String temp: scanBeanMap.keySet()){
Class<?> clazz = Class.forName(scanBeanMap.get(temp));
//判斷是否實現了BeanPostProcessor接口
if(BeanPostProcessor.class.isAssignableFrom(clazz)){
//實例化讓如臨時容器
postProcessorStrList.add((BeanPostProcessor)createBean(temp));
}
}
//將實現了postProcessor接口的bean加入processorBeanList中
for(BeanPostProcessor obj: postProcessorStrList){
processorBeanList.add(obj);
}
//再次循環scanBeanMap初始化所用bean
for(String temp: scanBeanMap.keySet()){
createBean(temp);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
//bean實例化
public Object createBean(String beanName){
//從緩存中獲取
if(beanCache.containsKey(beanName)){
return beanCache.get(beanName);
}else{
//緩存中取不到,則進行建立後加入緩存
try {
Class<?> clazz = Class.forName(scanBeanMap.get(beanName));
//processor前置方法執行
for(BeanPostProcessor processor : processorBeanList){
processor.postProcessBeforeInitialization(clazz, beanName);
}
//bean實例化
Object result = clazz.getConstructor().newInstance();
//processor後置方法執行
for(BeanPostProcessor processor : processorBeanList){
processor.postProcessAfterInitialization(result, beanName);
}
//將bean加入緩存
beanCache.put(beanName, result);
return result;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e){
e.printStackTrace();
}
}
return null;
}
}
複製代碼
代碼調用
public static void main(String[] args) {
PostProcessor postProcessor = new PostProcessor();
//添加掃描到的bean
postProcessor
.addBeanInfo("SecondBean", "net.postProcessor.SecondBean")
.addBeanInfo("CustomerPostProcessor", "net.postProcessor.CustomerPostProcessor");
postProcessor.execute();
}
//執行結果
執行CustomerPostProcessor的構造方法
class net.postProcessor.SecondBean======BeforeInitialization======SecondBean
SecondBean構造方法!world
net.postProcessor.SecondBean@1b40d5f0======AfterInitialization======SecondBean
複製代碼
代碼邏輯以下:
循環bean信息列表,將BeanPostProcessor接口bean分離出來優先實例化(實例化中緩存bean對象),並將之放入臨時容器。
循環完成,將臨時容器中的BeanPostProcessor接口bean賦值到全局BeanPostProcessor接口列表中
再次循環bean信息列表,緩存存在則直接返回緩存對象,不存在則進行bean實例化,期間循環調用全局BeanPostProcessor接口對象方法
咱們要從spring中的refresh()開始看起:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//刷新準備
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//告訴子類刷新內部bean工廠。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//爲容器準備bean工程
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//容許在上下文bean的後處理工廠子類。
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//優先將BeanDefinitionRegistryPostProcessor\BeanFactoryPostProcessor接口的bean對象實例化
//屬於spring內部組件調用
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//處理用戶自定義PostProcessor接口對象,以後加入spring的beanPostProcessors列表,
// 供以後預實例化其餘bean時觸發這些PostProcessor方法
registerBeanPostProcessors(beanFactory);
//...省略代碼
//實例化全部(non-lazy-init)單件。
finishBeanFactoryInitialization(beanFactory);
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
//bean銷燬
destroyBeans();
// Reset 'active' flag.
//取消刷新
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
//重置公共緩存
resetCommonCaches();
}
}
}
複製代碼
其中包含有postProcess字段都有可能和BeanProcessor相關,這裏有三個相關方法:
因此registerBeanPostProcessors()就是咱們要找的對象,來跟進看下registerBeanPostProcessors():
//AbstractApplicationContext#registerBeanPostProcessors
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//委託給PostProcessorRegistrationDelegate.registerBeanPostProcessors進行處理
PostProcessorRegistrationDelegate.registerBeanPostProcessors進行處理(beanFactory, this);
}
複製代碼
繼續跟進PostProcessorRegistrationDelegate.registerBeanPostProcessors():
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//查詢實現了BeanPostProcessor接口的beanName
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
//根據beanName循環調用getBean進行實例化
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
//對BeanPostProcessor接口對象進行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
//將獲取到的PostProcessors接口對象加入到spring的beanPostProcessors列表
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
複製代碼
果真這裏就是處理BeanPostProcessor接口的地方,邏輯和以前的思路相似: