前言:在【spring源碼分析】IOC容器初始化(八)中屢次提到了前置處理與後置處理,本篇文章針對此問題進行分析。Spring對前置處理或後置處理主要經過BeanPostProcessor進行實現。html
BeanPostProcessor的做用:在Bean實例化先後,若是須要對Bean進行一些配置、增長一些本身的處理邏輯,則使用BeanPostProcessor。spring
定義一個類實現BeanPostProcessor接口:緩存
1 public class UserDefinedBeanPostProcessor implements BeanPostProcessor { 2 3 @Override 4 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 5 System.out.println("BeanName=" + beanName + " 初始化以前進入"); 6 if ("beanPostProcessorBase".equals(beanName)) { 7 BeanPostProcessorBase processorBase = (BeanPostProcessorBase) bean; 8 processorBase.setMsg("Hello BeanPostProcessor!!!!!!!"); 9 } 10 return bean; 11 } 12 13 @Override 14 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 15 System.out.println("BeanName=" + beanName + " 初始化以後進入"); 16 return bean; 17 } 18 19 public void showMsg() { 20 System.out.println("BeanPostProcessor Test!!!!!!"); 21 } 22 }
再定義一個基礎測試類:安全
1 public class BeanPostProcessorBase { 2 3 private String msg; 4 5 public String getMsg() { 6 return msg; 7 } 8 9 public void setMsg(String msg) { 10 this.msg = msg; 11 } 12 }
測試方法:app
1 @Test 2 public void beanPostProcessorTest() { 3 ApplicationContext context = new ClassPathXmlApplicationContext("com/dev/config/beanpostprocessor/beanpostprocessor.xml"); 4 BeanPostProcessorBase postProcessor = context.getBean(BeanPostProcessorBase.class); 5 System.out.println(postProcessor.getMsg()); 6 }
運行結果:ide
分析:函數
首先必須明確BeanPostProcessor的執行時機:AbstractAutowireCapableBeanFactory#initializeBean方法源碼分析
1 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { 2 // 安全模式 3 if (System.getSecurityManager() != null) { 4 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 5 // 激活Aware方法,對特殊bean處理:Aware、BeanClassLoaderAware、BeanFactoryAware 6 invokeAwareMethods(beanName, bean); 7 return null; 8 }, getAccessControlContext()); 9 } else { 10 // 非安全模式下激活Aware方法,對特殊bean處理:Aware、BeanClassLoaderAware、BeanFactoryAware 11 invokeAwareMethods(beanName, bean); 12 } 13 14 // 後置處理器 before 15 Object wrappedBean = bean; 16 if (mbd == null || !mbd.isSynthetic()) { 17 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 18 } 19 20 // 處理初始化方法 21 try { 22 invokeInitMethods(beanName, wrappedBean, mbd); 23 } catch (Throwable ex) { 24 throw new BeanCreationException( 25 (mbd != null ? mbd.getResourceDescription() : null), 26 beanName, "Invocation of init method failed", ex); 27 } 28 // 後置處理器 after 29 if (mbd == null || !mbd.isSynthetic()) { 30 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 31 } 32 33 return wrappedBean; 34 }
分析:post
BeanPostProcessor能夠理解爲是Spring的一個工廠鉤子(其實Spring提供一系列的鉤子,如Aware 、InitializingBean、DisposableBean),它是Spring提供的對象實例化階段強有力的擴展點,容許Spring在實例化bean階段對其進行定製化修改,比較常見的使用場景是處理標記接口實現類或者爲當前對象提供代理實現(例如 AOP)。測試
BeanPostProcessor的執行時機以下:
注意:通常的BeanFactory是不支持自動註冊BeanPostProcessor,需手動調用addBeanPostProcessor進行註冊,可是ApplicationContext支持自動註冊,可是在其註冊過程當中就會對BeanPostProcessor進行初始化並進緩存,所以在示例代碼中利用了基礎測試類來進行演示。
BeanPostProcessor的做用域是容器級別的,它只和所在的容器相關,當BeanPostProcessor完成註冊後,它會應用於全部跟它在同一容器內的bean。
by Shawn Chen,2019.05.05,上午。