1. 程式人生 > >context:component-scan標籤的use-default-filters屬性的作用以及原理分析

context:component-scan標籤的use-default-filters屬性的作用以及原理分析

一、背景

  我們在Spring+SpringMVC+Mybatis的整合開發中,經常會遇到事務配置不起作用等問題,那麼本文就來分析下出現這種問題可能的原因以及解決方式。

二、分析及原理窺探

  1.專案結構

  

  2.我們在spring-mvc.xml檔案中進行如下配置,這種方式會成功掃描到帶有@Controller註解的Bean,不會掃描帶有@Service/@Repository註解的Bean,是正確的。

<context:component-scan base-package="com.hafiz.www.controller">   
     <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
</context:component-scan>  

  3.但是如下方式,不僅僅掃描到帶有@Controller註解的Bean,還掃描到帶有@Service/@Repository註解的Bean,可能造成事務不起作用等問題。

<context:component-scan base-package="com.hafiz.www">   
     <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
</context:component-scan>  

這是因為什麼呢?下面讓我們來從原始碼進行分析。

  1.<context:component-scan>會交給org.springframework.context.config.ContextNamespaceHandler處理.

registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); 

  2.ComponentScanBeanDefinitionParser會讀取配置檔案資訊並組裝成org.springframework.context.annotation.ClassPathBeanDefinitionScanner進行處理。

  3.如果沒有配置<context:component-scan>的use-default-filters屬性,則預設為true,在建立ClassPathBeanDefinitionScanner時會根據use-default-filters是否為true來呼叫如下程式碼:

protected void registerDefaultFilters() {
  this.includeFilters.add(new AnnotationTypeFilter(Component.class));
  ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
  try {
    this.includeFilters.add(new AnnotationTypeFilter(
      ((Class<? extends Annotation>) cl.loadClass("javax.annotation.ManagedBean")), false));
     logger.info("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
  }
  catch (ClassNotFoundException ex) {
    // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
  }
  try {
    this.includeFilters.add(new AnnotationTypeFilter(
      ((Class<? extends Annotation>) cl.loadClass("javax.inject.Named")), false));
    logger.info("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
  }
  catch (ClassNotFoundException ex) {
    // JSR-330 API not available - simply skip.
  }
}

從以上原始碼我們可以看出預設ClassPathBeanDefinitionScanner會自動註冊對@Component、@ManagedBean、@Named註解的Bean進行掃描。

  4.在進行掃描時會通過include-filter/exclude-filter來判斷你的Bean類是否是合法的:

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
  for (TypeFilter tf : this.excludeFilters) {
    if (tf.match(metadataReader, this.metadataReaderFactory)) {
       return false;
    }
  }
  for (TypeFilter tf : this.includeFilters) {
    if (tf.match(metadataReader, this.metadataReaderFactory)) {
       AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
       if (!metadata.isAnnotated(Profile.class.getName())) {
          return true;
       }
       AnnotationAttributes profile = MetadataUtils.attributesFor(metadata, Profile.class);
       return this.environment.acceptsProfiles(profile.getStringArray("value"));
     }
   }
  return false;
}

從以上原始碼可看出:掃描時首先通過exclude-filter 進行黑名單過濾,然後通過include-filter 進行白名單過濾,否則預設排除。

三、結論

  在spring-mvc.xml中進行如下配置:

<context:component-scan base-package="com.hafiz.www"> 
     <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 
</context:component-scan>

則SpringMVC容器不僅僅掃描並註冊帶有@Controller註解的Bean,而且還掃描並註冊了帶有@Component的子註解@Service、@Reposity的Bean。因為use-default-filters預設為true。所以如果不需要預設的,則use-default-filters=“false”禁用掉。

  當我們進行上面的配置時,SpringMVC容器會把service、dao層的bean重新載入,從而造成新載入的bean覆蓋了老的bean,但事務的AOP代理沒有配置在spring-mvc.xml配置檔案中,造成事務失效。解決辦法是:在spring-mvc.xml配置檔案中的context:component-scan標籤中使用use-default-filters=“false”禁用掉預設的行為。

相關推薦

context:component-scan標籤use-default-filters屬性作用以及原理分析

一、背景   我們在Spring+SpringMVC+Mybatis的整合開發中,經常會遇到事務配置不起作用等問題,那麼本文就來分析下出現這種問題可能的原因以及解決方式。 二、分析及原理窺探   1.專案結構      2.我們在spring-mvc.xml檔案中進行如下配置,這種方式會成功掃描到帶

關於 use-default-filters 屬性的說明

---------------------------------------------------------------------------------------------------------------------------------------------------------

Spring context:component-scan屬性

<context:component-scan/> 配置項不但啟用了對類包進行掃描以實施註釋驅動 Bean 定義的功能,同時還啟用了註釋驅動自動注入的功能(即還隱式地在內部註冊了 AutowiredAnno

Spring中使用註解時啟用<context:component-scan/>

方式 log one tar ati out 文件 ext tail 在spring中使用註解方式時需要在spring配置文件中配置組件掃描器:http://blog.csdn.net/j080624/article/details/56277315 <context

解決Spring中使用context:component-scan命名空間配置錯誤

num lex odi exceptio type oca ted pac instance ** nested exception is org.xml.sax.SAXParseException; lineNumber: 16; columnNumber: 74; cv

Spring <context:annotation-config> 與<context-component-scan> 的作用

sca beans 註解 component posit 復制代碼 npos tro autowired <context:annotation-config> 是用於激活那些已經在spring容器裏註冊過的bean(無論是通過xml的方式還是通過packag

今日收獲-context:component-scan

desire alc detect con repos pre app component vid 一、要有命名空間 xmlns:context="http://www.springframework.org/schema/context" 二、作用:直接上解釋吧! Sca

Spring 註解<context:annotation-config> 和 <context:component-scan>的作用與區別

poi dao lis 運行 ima scrip support .... res <context:annotation-config> 是用於激活那些已經在spring容器裏註冊過的bean(無論是通過xml的方式還是通過packagesanning的方式)

spring配置中《context:annotation-config》 和 《context:component-scan》區別

看到網上有很多大神的文章講解,講得很好很深,可是我沒有用到過,理解不了,在這寫一點我自己理解的區別。   如果想使用@AutoWired註解,需要在Spring配置檔案中配置<context:annotation-config> 。   <con

Spring配置項<context:component-scan/>和<context:annotation-config/>

<context:annotation-config/> 這是一條向Spring容器中註冊 AutowiredAnnotationBeanPostProcessor CommonAnnotationBeanPostProcessor PersistenceAnnotationBeanPos

context:component-scan 的使用說明

轉載地址:https://blog.csdn.net/qwe5810658/article/details/74343228 通常情況下我們在建立spring專案的時候在xml配置檔案中都會配置這個標籤,配置完這個標籤後,spring就會去自動掃描base-package對應的路徑或者該路徑的子包下面的ja

<context:annotation-config> 和 <context:component-scan>的區別

<context:annotation-config> 和 <context:component-scan>的區別 <context:annotation-config> 是用於啟用那些已經在spring容器裡註冊過的bean(無論是通過xml的方式還是通過pa

Spring 配置context:component-scan產生的錯誤

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://

spring註解注入和context:component-scan

  一、spring註解 @Service告訴spring容器,這是一個Service類,標識持久層Bean元件,預設情況會自動載入它到spring容器中。 @Autowried註解告訴spring,這個欄位需要自動注入 @Scope指定此spring bean的scope

Spring 開啟Annotation context:annotation-config 和 context:component-scan詮釋及區別

<context:annotation-config> 和 <context:component-scan>的區別 <context:annotation-config> 是用於啟用那些已經在spring容器裡註冊過的bean(無論是通過xml的方式

spring xml配置bean和context:component-scan掃描註解註冊bean的區別

本文啟動spring容器用的是dubbo的main方法 1.xml配置bean: 2.<context:component-scan>掃描註解註冊bean: 測試猜測結果: 前者啟動spring容器時建立bean

Spring MVC <context:annotation-config> 與 <context:component-scan>

  在MVC的配置檔案中,二者常出現,功能相似。簡單做個比較   <context:annotation-config> 用於啟用應用上下文中已經註冊的bean的註解,無論你的bean是通過什麼方式註冊的,例如通過<context:component-scan>註冊,或者在Sprin

SpringMVC配置檔案詳解:<context:annotation-config/>和<context:component-scan base-package=""/>和<mvc:annotation-driven /> Spring配置檔

原文地址:https://www.cnblogs.com/lcngu/p/5080702.html Spring配置檔案詳解:<context:annotation-config/>和<context:component-scan base-package=""/>和<mvc:

Spring 開啟Annotation <context:annotation-config> 和 <context:component-scan>詮釋及區別

<context:annotation-config> 和 <context:component-scan>的區別 <context:annotation-config> 是用於啟用那些已經在spring容器裡註冊過的bean(無論是通過xml的方式還是通過package

spring註解注入:<context:component-scan>詳解

spring從2.5版本開始支援註解注入,註解注入可以省去很多的xml配置工作。由於註解是寫入java程式碼中的,所以註解注入會失去一定的靈活性,我們要根據需要來選擇是否啟用註解注入。 我們首先看一個註解注入的實際例子,然後再詳細介紹context:component-scan的使用。 如果你已經在用