最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談BeanPostProcessor加載次序及其對(duì)Bean造成的影響分析

 更新時(shí)間:2019年04月07日 15:08:31   作者:不動(dòng)明王1984  
這篇文章主要介紹了淺談BeanPostProcessor加載次序及其對(duì)Bean造成的影響分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

BeanPostProcessor是一個(gè)工廠鉤子,允許Spring框架在新創(chuàng)建Bean實(shí)例時(shí)對(duì)其進(jìn)行定制化修改。例如:通過(guò)檢查其標(biāo)注的接口或者使用代理對(duì)其進(jìn)行包裹。應(yīng)用上下文會(huì)從Bean定義中自動(dòng)檢測(cè)出BeanPostProcessor并將它們應(yīng)用到隨后創(chuàng)建的任何Bean上。

普通Bean對(duì)象的工廠允許在程序中注冊(cè)post-processors,應(yīng)用到隨后在本工廠中創(chuàng)建的所有Bean上。典型的場(chǎng)景如:post-processors使用postProcessBeforeInitialization方法通過(guò)特征接口或其他類似的方式來(lái)填充Bean;而為創(chuàng)建好的Bean創(chuàng)建代理則一般使用postProcessAfterInitialization方法。

BeanPostProcessor本身也是一個(gè)Bean,一般而言其實(shí)例化時(shí)機(jī)要早過(guò)普通的Bean,但是BeanPostProcessor也會(huì)依賴一些Bean,這就導(dǎo)致了一些Bean的實(shí)例化早于BeanPostProcessor,由此會(huì)導(dǎo)致一些問(wèn)題。最近在處理shiro和spring cache整合時(shí)就碰到了,導(dǎo)致的結(jié)果就是spring cache不起作用?,F(xiàn)將問(wèn)題場(chǎng)景、查找歷程及解決方法展現(xiàn)一下。

1 問(wèn)題場(chǎng)景

打算在項(xiàng)目中將shiro與spring cache整合,使用spring cache統(tǒng)一管理緩存,也包括shiro認(rèn)證時(shí)的用戶信息查詢。項(xiàng)目中將service分層,outter層負(fù)責(zé)權(quán)限和session,inner層主打事務(wù)和緩存并與DAO交互,兩層之間也可以較容易的擴(kuò)展為RPC或微服務(wù)模式。因此在shiro的authRealm中依賴了innerUserService,并在innerUserService中配置了spring cache的標(biāo)注,使用cache進(jìn)行緩存。配置如下(摘錄重要部分):

  @Bean(name="shiroFilter")
  public ShiroFilterFactoryBean shiroFilter(
   @Qualifier("securityManager") SecurityManager manager
   ) {
    ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
    bean.setSecurityManager(manager);
    ..............
    return bean;
  }
  //配置核心安全事務(wù)管理器
  @Bean(name="securityManager")
  public SecurityManager securityManager(@Qualifier("authRealm") AuthorizingRealm authRealm,
   @Qualifier("sessionManager") SessionManager sessionManager,
   @Qualifier("cookieRememberMeManager") RememberMeManager rememberMeManager,
   @Qualifier("cacheManager") CacheManager cacheManager) {
    System.err.println("--------------shiro已經(jīng)加載----------------");
    DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
    manager.setRealm(authRealm);
    manager.setSessionManager(sessionManager);
    manager.setRememberMeManager(rememberMeManager);
    manager.setCacheManager(cacheManager);
    return manager;
  }
  //配置自定義權(quán)限登錄器
  @Bean(name="authRealm")
  public AuthorizingRealm authRealm(IInnerUserService userService) {
   MyRealm myrealm = new MyRealm(IInnerUserService);
   logger.info("authRealm myRealm initiated!");
    return myrealm;
  }
  @Bean
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
   return new LifecycleBeanPostProcessor(Ordered.LOWEST_PRECEDENCE);
  }

其中MyRealm是自定義的shiro AuthorizingRealm,用于執(zhí)行認(rèn)證與授權(quán),其實(shí)現(xiàn)依賴innerUserService從庫(kù)中查找用戶信息,示例代碼如下:

public class MyRealm extends AuthorizingRealm {
 IInnerUserService userService;
 public MyRealm(){
 super();
 }
 public MyRealm(IInnerUserService userService){
 this.userService = userService;
 }
 public IInnerUserService getUserService() {
 return userService;
 }
 public void setUserService(IInnerUserService userService) {
 this.userService = userService;
 }
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(
  PrincipalCollection principals) {
 //null usernames are invalid
    if (principals == null) {
      throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
    }
    Set<String> roleNames = new HashSet<String>();
    Set<String> permissions = new HashSet<String>();
 User user = (User)getAvailablePrincipal(principals);
 roleNames.add("role1");
 roleNames.add("role2");
 permissions.add("user:create");
 permissions.add("user:update");
 permissions.add("user:delete");
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
    info.setStringPermissions(permissions);
    return info;
 }
 
 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(
  AuthenticationToken token) throws AuthenticationException {
 String username = (String)token.getPrincipal(); //得到用戶名 
    String password = new String((char[])token.getCredentials()); //得到密碼 
    User user = userService.findByUsernameInner(username);
    if(user==null){
     throw new UnknownAccountException();
    }else if(!password.equals(user.getPassword()))
 {
     throw new IncorrectCredentialsException();
 }
    else{
     return new SimpleAuthenticationInfo(user, password, getName());
    }
 }
}

而在innerUserService中配置了spring cache的標(biāo)注,示例代碼如下:

@Service
public class IInnerUserServiceImpl implements IInnerUserService {
 Logger logger = LoggerFactory.getLogger(IInnerUserServiceImpl.class);
 
 @Autowired
 IUserDao userDao;
 
 @Override
 @Cacheable(value = "mycache", key = "#username")
 public User findByUsernameInner(String username) {
 User user = userDao.findByUsername(username);
 logger.info("Real execute find from database, username:{}", username);
 return user;
 }
}

并在配置文件上標(biāo)注了@EnableCaching(mode=AdviceMode.PROXY)以啟動(dòng)spring cache。這里不過(guò)多解釋具體shiro和spring cache的使用,有興趣的同學(xué)請(qǐng)自行搜索相關(guān)資料。

按理說(shuō)這樣的配置在認(rèn)證的時(shí)候應(yīng)該可以直接使用到innerUserService中配置的spring cache緩存。

但,問(wèn)題出現(xiàn)了,當(dāng)authRealm中依賴了innerUserService以后,定義在innerUserService上的spring cache就神奇的失效了。而authRealm不依賴innerUserService的時(shí)候,cache卻運(yùn)行的好好的。

接下來(lái)是問(wèn)題查找的路徑。

2 解決問(wèn)題之旅

2.1 spring cache失效的表象原因

首先要找到spring cache失效的表象/直接原因,我們知道spring cache使用Spring AOP和攔截器的方式攔截定義了特定標(biāo)注的方法,然后執(zhí)行特定邏輯。因此其實(shí)現(xiàn)依賴于動(dòng)態(tài)代理機(jī)制auto-proxy,而經(jīng)過(guò)初步調(diào)試發(fā)現(xiàn),當(dāng)被authRealm依賴以后,innerUserService就不會(huì)被代理了,因此無(wú)從進(jìn)入AOP的pointcut,也就是說(shuō)AOP切面失效了!

2.2 從spring cache的集成機(jī)制分析深層次原因

為何沒(méi)有被代理呢,我們先來(lái)確認(rèn)一下正常情況下什么時(shí)候進(jìn)行代理封裝,這時(shí)關(guān)于BeanPostProcessor的定義浮現(xiàn)腦海,據(jù)文檔記載BeanPostProcessor允許在Bean實(shí)例化的前后對(duì)其做一些猥瑣的事情,比如代理。我們?cè)贐eanPostProcessor的實(shí)現(xiàn)類中發(fā)現(xiàn)了InstantiationAwareBeanPostProcessor、SmartInstantiationAwareBeanPostProcessor、AbstractAutoProxyCreator、InfrastructureAdvisorAutoProxyCreator這一脈。而反觀@enableCache標(biāo)注在啟動(dòng)的時(shí)候會(huì)@import CachingConfigurationSelector,其selectImports方法會(huì)返回AutoProxyRegistrar和ProxyCachingConfiguration的全類名(我們定義了mode=AdviceMode.PROXY),也就是加載這兩個(gè)類。第一個(gè)的作用就是注冊(cè)InfrastructureAdvisorAutoProxyCreator到BeanDefinitionRegistry中。第二個(gè)的作用就是注冊(cè)了BeanFactoryCacheOperationSourceAdvisor和CacheInterceptor。

因此,當(dāng)正常情況下,一個(gè)添加了spring cache相關(guān)標(biāo)注的bean會(huì)在創(chuàng)建后被InfrastructureAdvisorAutoProxyCreator基于advisor進(jìn)行代理增強(qiáng),代理后便可在攔截器CacheInterceptor中對(duì)其方法進(jìn)行攔截,然后執(zhí)行cache相關(guān)邏輯。此處省略具體處理邏輯,有興趣請(qǐng)參考相關(guān)文檔。

所以第一懷疑就是innerUserService沒(méi)有經(jīng)過(guò)InfrastructureAdvisorAutoProxyCreator的代理增強(qiáng)。果然調(diào)試發(fā)現(xiàn),被authRealm依賴的情況下在InnerUserService的Bean實(shí)例化時(shí),用于處理該Bean的PostBeanProcessor明顯比沒(méi)被authRealm依賴時(shí)少,并且不含有InfrastructureAdvisorAutoProxyCreator。

而且,被依賴時(shí)會(huì)多打出來(lái)一行信息:

...................
Bean 'IInnerUserServiceImpl' of type [shiro.web.inner.service.impl.IInnerUserServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
...................

據(jù)此推斷,可能是innerUserService啟動(dòng)時(shí)機(jī)過(guò)早,導(dǎo)致的后面那些BeanPostProcessor們來(lái)沒(méi)來(lái)得及實(shí)例化及注冊(cè)呢。

2.3 BeanPostProcessor啟動(dòng)階段對(duì)其依賴的Bean造成的影響

首先確認(rèn)了authRealm也是受害者,因?yàn)閟hiroFilter->SecurityManager->authRealm的依賴關(guān)系導(dǎo)致其不得不提前實(shí)例化。表面上的罪魁禍?zhǔn)资莝hiroFilter,但是到底是誰(shuí)導(dǎo)致的shiroFilter預(yù)料之外的提前啟動(dòng)呢。shiroFilter與InfrastructureAdvisorAutoProxyCreator的具體啟動(dòng)時(shí)機(jī)到底是什么時(shí)候呢。

又經(jīng)過(guò)一番混天暗地的調(diào)試,終于了解了BeanPostProcessor的啟動(dòng)時(shí)機(jī)。在AbstractBeanFactory中維護(hù)了BeanPostProcessor的列表:

private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();

 

并實(shí)現(xiàn)了ConfigurableBeanFactory定義的方法:

void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

因此我們首先監(jiān)控AbstractBeanFactory.addBeanPostProcessor(),看看啟動(dòng)過(guò)程中誰(shuí)調(diào)用了該方法來(lái)注冊(cè)BeanPostProcessor。發(fā)現(xiàn)實(shí)例化及注冊(cè)PostBeanFactory的階段分為四個(gè): 

第一階段是在啟動(dòng)時(shí)調(diào)用過(guò)程會(huì)調(diào)用AbstractApplicationContext.refresh(),其中的prepareBeanFactory方法中注冊(cè)了

ApplicationContextAwareProcessor、ApplicationListenerDetector:
........
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
........
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
........

然后在postProcessBeanFactory方法中注冊(cè)了WebApplicationContextServletContextAwareProcessor:

beanFactory.addBeanPostProcessor(
  new WebApplicationContextServletContextAwareProcessor(this));

然后在invokeBeanFactoryPostProcessors方法中調(diào)用

復(fù)制代碼 代碼如下:
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

其中對(duì)已經(jīng)注冊(cè)的BeanFactoryPostProcessors挨個(gè)調(diào)用其postProcessBeanFactory方法,其中有一個(gè)ConfigurationClassPostProcessor,其postProcessBeanFactory方法中注冊(cè)了一個(gè)ImportAwareBeanPostProcessor:

beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));

最后在registerBeanPostProcessors方法中調(diào)用

PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);

在該方法中,首先注冊(cè)BeanPostProcessorChecker:

復(fù)制代碼 代碼如下:
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

該BeanPostProcessorChecker就是輸出上面那行信息的真兇,它會(huì)在Bean創(chuàng)建完后檢查可在當(dāng)前Bean上起作用的BeanPostProcessor個(gè)數(shù)與總的BeanPostProcessor個(gè)數(shù),如果起作用的個(gè)數(shù)少于總數(shù),則報(bào)出上面那句信息。

然后分成三個(gè)階段依次實(shí)例化并注冊(cè)實(shí)現(xiàn)了PriorityOrdered的BeanPostProcessor、實(shí)現(xiàn)了Ordered的BeanPostProcessor、沒(méi)實(shí)現(xiàn)Ordered的BeanPostProcessor,代碼如下:

 // Separate between BeanPostProcessors that implement PriorityOrdered,
 // Ordered, and the rest.
 List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
 List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
 List<String> orderedPostProcessorNames = new ArrayList<String>();
 List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
 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.
 sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
 registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
 
 
 // Next, register the BeanPostProcessors that implement Ordered.
 List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
 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<BeanPostProcessor>();
 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));

需要注意的是,除了第一個(gè)階段,其他階段同一個(gè)階段的BeanPostProcessor是在全部實(shí)例化完成以后才會(huì)統(tǒng)一注冊(cè)到beanFactory的,因此,同一個(gè)階段的BeanPostProcessor及其依賴的Bean在實(shí)例化的時(shí)候是無(wú)法享受到相同階段但是先實(shí)例化的BeanPostProcessor的“服務(wù)”的,因?yàn)樗鼈冞€沒(méi)有注冊(cè)。

從上面調(diào)試與源代碼分析,BeanPostProcessor的實(shí)例化與注冊(cè)分為四個(gè)階段,第一階段applicationContext內(nèi)置階段、第二階段priorityOrdered階段、第三階段Ordered階段、第四階段nonOrdered階段。而B(niǎo)eanPostProcessor同時(shí)也是Bean,其注冊(cè)之前一定先實(shí)例化。而且是分批實(shí)例化和注冊(cè),也就是屬于同一批的BeanPostProcesser全部實(shí)例化完成后,再全部注冊(cè),不存在先實(shí)例化先注冊(cè)的問(wèn)題。而在實(shí)例化的時(shí)候其依賴的Bean同樣要先實(shí)例化。 

因此導(dǎo)致一個(gè)結(jié)果就是,被PriorityOrderedBeanPostProcessor所依賴的Bean其初始化時(shí)無(wú)法享受到PriorityOrdered、Ordered、和nonOrdered的BeanPostProcessor的服務(wù)。而被OrderedBeanPostProcessor所依賴的Bean無(wú)法享受Ordered、和nonOrdered的BeanPostProcessor的服務(wù)。最后被nonOrderedBeanPostProcessor所依賴的Bean無(wú)法享受到nonOrderedBeanPostProcessor的服務(wù)。

由于InfrastructureAdvisorAutoProxyCreator的啟動(dòng)階段是Ordered,因此我們需要確保沒(méi)有任何priorityOrdered和Ordered的BeanPostProcessor直接或間接的依賴到shiroFilter,也就是依賴到我們的innerUserService。

同時(shí),在PriorityOrdered接口的注解中也提到了該情況:

Note: {@code PriorityOrdered} post-processor beans are initialized in
  * a special phase, ahead of other post-processor beans. This subtly
  * affects their autowiring behavior: they will only be autowired against
  * beans which do not require eager initialization for type matching.

2.4 BeanPostProcessor在進(jìn)行依賴的Bean注入時(shí),根據(jù)Bean名稱進(jìn)行類型檢查時(shí)導(dǎo)致的“誤傷”

OK,問(wèn)題貌似已查明,修改Configuration中所有PriorityOrdered和Ordered類型的PostBeanProcessor的Bean配置,使其不再依賴shiroFilter。再次啟動(dòng),卻發(fā)現(xiàn)仍然提前啟動(dòng)了shiroFilter->SecurityManager->authRealm->innerUserService。

百思不得其解,又是一輪昏天暗地的調(diào)試,查找shiroFilter具體的啟動(dòng)時(shí)機(jī)。發(fā)現(xiàn)在一個(gè)叫做dataSourceInitializerPostProcessor的BeanPostProcessor實(shí)例化的時(shí)候,在根據(jù)類型獲得其依賴的參數(shù)時(shí),對(duì)shiroFilter執(zhí)行了初始化。導(dǎo)致后續(xù)SecurityManager->authRealm->innerUserService統(tǒng)統(tǒng)提前初始化。但是在dataSourceInitializerPostProcessor之前的BeanPostProcessor卻沒(méi)有。經(jīng)調(diào)試它們是否會(huì)導(dǎo)致shiroFilter初始化的區(qū)別在調(diào)用AbstractBeanFactory.isTypeMatch方法時(shí)出現(xiàn):

 public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException{
 .....................
 // Check bean class whether we're dealing with a FactoryBean.
 if (FactoryBean.class.isAssignableFrom(beanType)) { //(1)判斷名稱對(duì)應(yīng)的Bean是否是一個(gè)FactoryBean,若是FactoryBean才執(zhí)行本句
  if (!BeanFactoryUtils.isFactoryDereference(name)) {
  // If it's a FactoryBean, we want to look at what it creates, not the factory class.
  beanType = getTypeForFactoryBean(beanName, mbd);
  if (beanType == null) {
   return false;
  }
  }
 } 
 .....................
 }

然后進(jìn)入AbstractAutowireCapableBeanFactory.getTypeForFactoryBean方法:

 @Override
 protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
 String factoryBeanName = mbd.getFactoryBeanName();
 String factoryMethodName = mbd.getFactoryMethodName();
 
 
 if (factoryBeanName != null) {
  if (factoryMethodName != null) {
  // Try to obtain the FactoryBean's object type from its factory method declaration
  // without instantiating the containing bean at all.
  BeanDefinition fbDef = getBeanDefinition(factoryBeanName);
  if (fbDef instanceof AbstractBeanDefinition) {
   AbstractBeanDefinition afbDef = (AbstractBeanDefinition) fbDef;
   if (afbDef.hasBeanClass()) {
   Class<?> result = getTypeForFactoryBeanFromMethod(afbDef.getBeanClass(), factoryMethodName);
   if (result != null) {
    return result;
   }
   }
  }
  }
  // If not resolvable above and the referenced factory bean doesn't exist yet,
  // exit here - we don't want to force the creation of another bean just to
  // obtain a FactoryBean's object type...
  if (!isBeanEligibleForMetadataCaching(factoryBeanName)) {  //(2)判斷該bean對(duì)應(yīng)的factoryBeanName是否已經(jīng)初始化了,如果沒(méi)有,就返回。如果有,則繼續(xù)
  return null;
  }
 }
 
 
 // Let's obtain a shortcut instance for an early getObjectType() call...
 FactoryBean<?> fb = (mbd.isSingleton() ?
  getSingletonFactoryBeanForTypeCheck(beanName, mbd) :
  getNonSingletonFactoryBeanForTypeCheck(beanName, mbd));
 
 
 ......................
 }

其中,有一個(gè)重要的判斷:

    // If not resolvable above and the referenced factory bean doesn't exist yet,
 // exit here - we don't want to force the creation of another bean just to
 // obtain a FactoryBean's object type...
 if (!isBeanEligibleForMetadataCaching(factoryBeanName)) {
 return null;
 }

注解說(shuō)的很明確,如果名字對(duì)應(yīng)的factoryBean所在的factoryBean工廠尚未解析并實(shí)例化,那就直接退出,不會(huì)強(qiáng)制創(chuàng)建該facotryBean工廠,也就是Configuration對(duì)應(yīng)的Bean。再次調(diào)試,果然發(fā)現(xiàn),在先前的BeanPostProcessor和dataSourceInitializerPostProcessor之間,存在一個(gè)lifecycleBeanPostProcessor,而lifecycleBeanPostProcessor是在我們的Configuration中顯示定義的,因此,當(dāng)lifecycleBeanPostProcessor啟動(dòng)時(shí)會(huì)導(dǎo)致Configuration實(shí)例化。 

dataSourceInitializerPostProcessor和在它之前的BeanPostProcessor對(duì)shiroFilter行為的不同在這里得到了完美的解釋。本質(zhì)上說(shuō)dataSourceInitializerPostProcessor并不重要,重要的是lifecycleBeanPostProcessor將Configuration初始化了。就算不是dataSourceInitializerPostProcessor,那另一個(gè)BeanPostProcessor實(shí)例化時(shí)同樣會(huì)將shiroFilter初始化。

最終隱藏大BOSS查明,解決方案就簡(jiǎn)單了,將lifecycleBeanPostProcessor移出到一個(gè)單獨(dú)的Configuration就好了。

3. 總結(jié)

3.1 BeanPostProcessor啟動(dòng)順序,以及其對(duì)于依賴的Bean的影響

BeanPostProcessor的啟動(dòng)時(shí)機(jī)。分為四個(gè)階段,第一階段context內(nèi)置階段、第二階段priorityOrdered階段、第三階段Ordered階段、第四階段nonOrdered階段。

而B(niǎo)eanPostProcessor同時(shí)也是Bean,其注冊(cè)之前一定先實(shí)例化。而且是分批實(shí)例化和注冊(cè),也就是屬于同一批的BeanPostProcesser全部實(shí)例化完成后,再全部注冊(cè),不存在先實(shí)例化先注冊(cè)的問(wèn)題。而在實(shí)例化的時(shí)候其依賴的Bean同樣要先實(shí)例化。

因此導(dǎo)致一個(gè)結(jié)果就是,被PriorityOrderedBeanPostProcessor所依賴的Bean其初始化以后無(wú)法享受到PriorityOrdered、Ordered、和nonOrdered的BeanPostProcessor的服務(wù)。而被OrderedBeanPostProcessor所依賴的Bean無(wú)法享受Ordered、和nonOrdered的BeanPostProcessor的服務(wù)。最后被nonOrderedBeanPostProcessor所依賴的Bean無(wú)法享受到nonOrderedBeanPostProcessor的服務(wù)。

3.2 注意避免BeanPostProcessor啟動(dòng)時(shí)的“誤傷”陷阱

BeanPostProcessor實(shí)例化時(shí),自動(dòng)依賴注入根據(jù)類型獲得需要注入的Bean時(shí),會(huì)將某些符合條件的Bean(FactoryBean并且其FactoryBeanFactory已經(jīng)實(shí)例化的)先實(shí)例化,如果此FacotryBean又依賴其他普通Bean,會(huì)導(dǎo)致該Bean提前啟動(dòng),造成誤傷(無(wú)法享受部分BeanPostProcessor的后處理,例如典型的auto-proxy)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

泊头市| 康马县| 白山市| 江油市| 新竹市| 淮北市| 贞丰县| 达尔| 枞阳县| 大丰市| 荆州市| 桂东县| 富民县| 化德县| 绥中县| 和静县| 崇州市| 东明县| 常州市| 鲜城| 秦安县| 高雄市| 鹤山市| 湖北省| 繁昌县| 本溪市| 巫山县| 乌审旗| 奉节县| 黄石市| 宝坻区| 新邵县| 东光县| 卢氏县| 广南县| 呼和浩特市| 宁河县| 临澧县| 蒙自县| 宁武县| 华安县|