溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

BeanPostProcessor怎么在spring中的應(yīng)用

發(fā)布時間:2022-03-24 15:31:08 來源:億速云 閱讀:222 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹了BeanPostProcessor怎么在spring中的應(yīng)用的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇BeanPostProcessor怎么在spring中的應(yīng)用文章都會有所收獲,下面我們一起來看看吧。

1.BeanPostProcessor 執(zhí)行原理

1)斷點查看代碼  
1.在MyBeanPostProcessor添加斷點,運行測試方法通過觀察棧,查看執(zhí)行流程

BeanPostProcessor怎么在spring中的應(yīng)用

下方長長的英文是調(diào)試中右下角的窗口:

BeanPostProcessor怎么在spring中的應(yīng)用

2.  <init>:84, AnnotationConfigApplicationContext 初始化容器  
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {    this();    register(annotatedClasses);    refresh();  }
3.  refresh:543, AbstractApplicationContext  調(diào)用refresh() 函數(shù) ,實例化所有剩余的單例  
// Instantiate all remaining (non-lazy-init) singletons.        finishBeanFactoryInitialization(beanFactory);
4  .finishBeanFactoryInitialization:867, AbstractApplicationContext   
// Instantiate all remaining (non-lazy-init) singletons.    beanFactory.preInstantiateSingletons();
preInstantiateSingletons:761, DefaultListableBeanFactory,具體通過getBean函數(shù)進行初始化剩余的Bean
getBean(beanName);
5.  doGetBean:302, AbstractBeanFactory 這一步  通過getSingleton  獲取單實例,  通過初始化createBean 方法創(chuàng)建Bean
// Create bean instance.        if (mbd.isSingleton()) {          sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {            @Override            public Object getObject() throws BeansException {              try {                return createBean(beanName, mbd, args);              }              catch (BeansException ex) {                // Explicitly remove instance from singleton cache: It might have been put there                // eagerly by the creation process, to allow for circular reference resolution.                // Also remove any beans that received a temporary reference to the bean.                destroySingleton(beanName);                throw ex;              }            }          });          bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);        }
6.  createBean:483, AbstractAutowireCapableBeanFactory,調(diào)用初始化,獲取Bean 實例  
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
7.  doCreateBean:555, AbstractAutowireCapableBeanFactory 進入到具體創(chuàng)建Bean 中   通過populateBean()  進行填充Bean 操作
Object exposedObject = bean;    try {      populateBean(beanName, mbd, instanceWrapper);      if (exposedObject != null) {        exposedObject = initializeBean(beanName, exposedObject, mbd);      }    }
8.最后可以看到  initializeBean:1620, AbstractAutowireCapableBeanFactory 中 執(zhí)行  applyBeanPostProcessorsBeforeInitialization 和  applyBeanPostProcessorsAfterInitialization 進行  postProcessBeforeInitialization() 函數(shù)和postProcessAfterInitialization() 函數(shù)的調(diào)用;中間調(diào)用  invokeInitMethods(beanName, wrappedBean, mbd)  ;進行  初始化  函數(shù)的調(diào)用
Object wrappedBean = bean;    if (mbd == null || !mbd.isSynthetic()) {      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);    }
   try {      invokeInitMethods(beanName, wrappedBean, mbd);    }    catch (Throwable ex) {      throw new BeanCreationException(          (mbd != null ? mbd.getResourceDescription() : null),          beanName, "Invocation of init method failed", ex);    }
   if (mbd == null || !mbd.isSynthetic()) {      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);    }
9.  applyBeanPostProcessorsBeforeInitialization:409,AbstractAutowireCapableBeanFactory    最后通過  getBeanPostProcessors()    掃描所有的   BeanPostProcessor   直到遇到null 進行返回退出循環(huán)
@Override  public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)      throws BeansException {
   Object result = existingBean;    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {      result = beanProcessor.postProcessBeforeInitialization(result, beanName);      if (result == null) {        return result;      }    }    return result;  }
2)  總結(jié)  運行過程中的執(zhí)行原理  
通過查看斷點調(diào)試結(jié)果, 可以看到,創(chuàng)建單例容器Bean 通過
populateBean() 函數(shù)進行填充,invokeInitMethods(beanName, wrappedBean, mbd);

函數(shù)進行初始化,然后前后有applyBeanPostProcessorsBeforeInitialization 和applyBeanPostProcessorsAfterInitialization 進行對所有的BeanPostProcessor 掃描執(zhí)行。

2.BeanPostProcessor 在spring 中的應(yīng)用

在spring 中大量使用BeanPostProcessor  ,進行處理,下面舉例3個進行斷點、代碼測試:
1).ApplicationContextAwareProcessor 幫助組件注入IOC 容器
在Dog 中實現(xiàn)  implements    ApplicationContextAware 接口,編寫,  setApplicationContext  將容器保存至屬性方法中
@Componentpublic class Dog implements ApplicationContextAware {  private ApplicationContext applicationContext;
 public Dog(){    System.out.println("dog constructor...");  }
 @Override  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {    // TODO Auto-generated method stub    this.applicationContext = applicationContext;  }}
1.  postProcessBeforeInitialization:97,ApplicationContextAwareProcessor 可以看到 通過  postProcessBeforeInitialization    函數(shù)進行將容器進行賦值

2.通過invokeAwareInterfaces判斷Bean 的類型進行類型轉(zhuǎn)換,并進行賦值

private void invokeAwareInterfaces(Object bean) {    if (bean instanceof Aware) {      if (bean instanceof EnvironmentAware) {        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());      }      if (bean instanceof EmbeddedValueResolverAware) {        ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);      }      if (bean instanceof ResourceLoaderAware) {        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);      }      if (bean instanceof ApplicationEventPublisherAware) {        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);      }      if (bean instanceof MessageSourceAware) {        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);      }      if (bean instanceof ApplicationContextAware) {        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);      }    }  }
2).InitDestroyAnnotationBeanPostProcessor 用于處理 @PostConstruct 、@PreDestroy 注解。
查看  InitDestroyAnnotationBeanPostProcessor  源碼,  postProcessBeforeInitialization    函數(shù)代碼,如下:
@Override  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());    try {      metadata.invokeInitMethods(bean, beanName);    }    catch (InvocationTargetException ex) {      throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());    }    catch (Throwable ex) {      throw new BeanCreationException(beanName, "Failed to invoke init method", ex);    }    return bean;  }
使用  findLifecycleMetadata(bean.getClass());  獲取所有的生命周期函數(shù),通過  metadata.invokeInitMethods(bean, beanName);    進行代理調(diào)用對應(yīng)的生命周期函數(shù)
public void invokeInitMethods(Object target, String beanName) throws Throwable {   Collection<LifecycleElement> initMethodsToIterate =         (this.checkedInitMethods != null ? this.checkedInitMethods : this.initMethods);   if (!initMethodsToIterate.isEmpty()) {      boolean debug = logger.isDebugEnabled();      for (LifecycleElement element : initMethodsToIterate) {         if (debug) {            logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());         }         element.invoke(target);      }   }}
3).BeanValidationPostProcessor 數(shù)據(jù)校驗
用于進行數(shù)據(jù)校驗,查看  BeanValidationPostProcessor 的源碼  postProcessBeforeInitialization 和  postProcessAfterInitialization 代碼如下,進行  doValidate()函數(shù)進行數(shù)據(jù)校驗。
@Override  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {    if (!this.afterInitialization) {      doValidate(bean);    }    return bean;  }
 @Override  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {    if (this.afterInitialization) {      doValidate(bean);    }    return bean;  }

關(guān)于“BeanPostProcessor怎么在spring中的應(yīng)用”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“BeanPostProcessor怎么在spring中的應(yīng)用”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI