`

<context:component-scan>使用说明(转)

 
阅读更多

 在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的Java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean

注意:如果配置了<context:component-scan>那么<context:annotation-config/>标签就可以不用再xml中配置了,因为前者包含了后者。另外<context:annotation-config/>还提供了两个子标签

1.        <context:include-filter>

2.       <context:exclude-filter>

在说明这两个子标签前,先说一下<context:component-scan>有一个use-default-filters属性,改属性默认为true,这就意味着会扫描指定包下的全部的标有@Component的类,并注册成bean.也就是@Component的子注解@Service,@Reposity等。所以如果仅仅是在配置文件中这么写

<context:component-scan base-package="tv.huan.weisp.web"/>

 Use-default-filter此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。

 

 可以发现这种扫描的粒度有点太大,如果你只想扫描指定包下面的Controller,该怎么办?此时子标签<context:incluce-filter>就起到了勇武之地。如下所示

<context:component-scan base-package="tv.huan.weisp.web .controller">  

<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   

</context:component-scan>  

这样就会只扫描base-package指定下的有@Controller下的java类,并注册成bean

但是因为use-dafault-filter在上面并没有指定,默认就为true,所以当把上面的配置改成如下所示的时候,就会产生与你期望相悖的结果(注意base-package包值得变化)

<context:component-scan base-package="tv.huan.weisp.web ">  

<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   

</context:component-scan>  

此时,spring不仅扫描了@Controller,还扫描了指定包所在的子包service包下注解@Service的java类

此时指定的include-filter没有起到作用,只要把use-default-filter设置成false就可以了。这样就可以避免在base-packeage配置多个包名这种不是很优雅的方法来解决这个问题了。

 

如果想在根路径下只扫描@Controller,应该设置为false,并使用include-filter:

 

<context:component-scan base-package="tv.huan.weisp.web" use-default-filters="false">
   <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

 

在base-package指定的包中有的子包是不含有注解了,所以不用扫描,此时可以指定<context:exclude-filter>来进行过滤,说明此包不需要被扫描。

 

综合以上说明:

Use-dafault-filters=”false”的情况下:<context:exclude-filter>指定的不扫描,<context:include-filter>指定的扫描。

 

===================================================================================

以下是网上其他说明:

 

如下方式可以成功扫描到@Controller注解的Bean,不会扫描@Service/@Repository的Bean。正确。

<context:component-scan base-package="org.bdp.system.test.controller">   
     <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
</context:component-scan>  

 但是如下方式,不仅仅扫描@Controller,还扫描@Service/@Repository的Bean,可能造成一些问题。

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

这个尤其在springmvc+spring+hibernate等集成时最容易出问题的地,最典型的错误就是:

事务不起作用!!! 

 

这是什么问题呢?

分析

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.  
}  

  

//@Service和@Controller都是Component,因为这些注解都添加了@Component注解

可以看到默认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;  
}  

 

 

默认扫描指定包下的全部 @Component, exclude-filter 指定的不扫描,include-filter指定的扫描, include-filter和exclude-filter 没有指定的仍然扫描。对;

指定了use-default-filters=“false” 是这样的
首先通过exclude-filter 进行黑名单过滤;

然后通过include-filter 进行白名单过滤;

否则默认排除

 

结论

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

 

为什么这段代码不仅仅扫描@Controller注解的Bean,而且还扫描了@Component的子注解@Service、@Reposity。因为use-default-filters默认为true。所以如果不需要默认的,则use-default-filters=“false”禁用掉。

 

 

请参考

《SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结》 

《第三章 DispatcherServlet详解 ——跟开涛学SpringMVC》中的ContextLoaderListener初始化的上下文和DispatcherServlet初始化的上下文关系。

 

如果在springmvc配置文件,不使用cn.javass.demo.web.controller前缀,而是使用cn.javass.demo,则service、dao层的bean可能也重新加载了,但事务的AOP代理没有配置在springmvc配置文件中,从而造成新加载的bean覆盖了老的bean,造成事务失效。只要使用use-default-filters=“false”禁用掉默认的行为就可以了。

 

问题不难,spring使用上的问题。总结一下方便再遇到类似问题的朋友参考。

 

 

分享到:
评论

相关推荐

    Spring扫描器—spring组件扫描使用详解

    在Spring框架中,`&lt;context:component-scan/&gt;`元素是核心组件扫描的基石,它允许我们自动检测和注册...在实际项目中,结合使用`@Component`家族注解和`&lt;context:component-scan/&gt;`,能够构建出高效、灵活的Spring应用。

    Spring 报错:元素 "context:component-scan" 的前缀 "context" 未绑定的问题解决

    &lt;context:component-scan base-package="com.makelove88.**.dao,com.makelove88.**.service" /&gt; &lt;import resource="classpath*:*/applicationContext-*.xml" /&gt; &lt;/beans&gt; ``` 在这个修正后的配置中,我们添加了 ...

    spring组件扫描contextcomponent-scan使用详解.pdf

    Spring 组件扫描&lt;context:component-scan/&gt;使用详解 在 Spring 框架中,组件扫描是指通过注解和 XML 配置来自动检测和加载Bean的过程。下面将详细介绍&lt;context:component-scan/&gt;标签的使用方式和原理。 一、...

    Spring注解详解

    &lt;/context:component-scan&gt; ``` 使用注解过滤某些类: ```xml &lt;context:component-scan base-package="com.example"&gt; &lt;context:include-filter type="annotation" expression="org.springframework.stereotype....

    框架ssm整合

    &lt;context:component-scan base-package="com.example.service"/&gt; ``` #### 五、实现业务逻辑 根据需求,需要实现用户数据的CRUD操作。可以通过以下步骤来实现: 1. **实体类**:设计User类,包含用户名、密码等...

    Spring MyBatis 整合

    &lt;context:component-scan base-package="com.example.service"/&gt; &lt;/beans&gt; ``` #### 六、编写实体类、DAO层与Service层 1. **实体类**:定义业务对象。 2. **DAO层**:定义Mapper接口,使用MyBatis注解或XML...

    集成springmvc spring hibernate的配置

    &lt;/context:component-scan&gt; ``` 2. **数据库连接配置**:我们需要从`jdbc.properties`文件中读取数据库连接信息。使用`context:property-placeholder`标签将属性文件加载到Spring上下文中。然后,配置数据源`...

    maven搭建SSM框架

    &lt;context:component-scan base-package="com.example.ssm.controller" /&gt; ``` 3. **Web.xml 配置**: - 配置`ContextLoaderListener`和`DispatcherServlet`。 - 示例代码如下: ```xml &lt;listener&gt; &lt;listener...

    springMVC框架搭建及详解

    &lt;context:component-scan base-package="com.example.controller"/&gt; &lt;!-- 视图解析器 --&gt; &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property ...

    使用Spring2.5的Autowired实现注释型的IOC

    在上面的配置文件中,我们使用了 `&lt;context:annotation-config/&gt;` 和 `&lt;context:component-scan base-package="testspring.main"/&gt;` 两个标签。 `&lt;context:annotation-config/&gt;` 用于启用注释型的 IOC,而 `&lt;context...

    SpringMVC入门

    - **扫描包含Controller的包**:通过`&lt;context:component-scan&gt;`元素指定需要扫描的包。 - **不处理静态资源**:通过`&lt;mvc:default-servlet-handler/&gt;`让Servlet容器处理静态资源。 - **启用注解驱动**:使用`&lt;mvc:...

    IDEASSM框架实战CRUDSSM整合配置MyBatis逆向工程.docx

    &lt;context:component-scan base-package="com.example.demo.controller" /&gt; &lt;!-- 视图解析器 --&gt; &lt;bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property name="prefix" ...

    15、spring 配置以及使用 1

    在这个主题中,我们将深入探讨`&lt;context:annotation-config&gt;`与`&lt;context:component-scan&gt;`的区别,事务管理器的配置,以及Spring开发环境的选择和数据源的配置。 1. `&lt;context:annotation-config&gt;`和`&lt;context:...

    ssm整合文档。看着文档自己操作,很简单

    &lt;context:component-scan base-package="com.example.controller" /&gt; ``` 其中`base-package`属性指定了控制器所在的包名。 - **配置事务管理器** 如果项目中涉及数据库操作,还需要配置事务管理器。 ```...

    学习ssm整理的xml配置笔记

    在本节中,我们将探讨 SSM 框架中 XML 配置的使用,特别是事务配置和 `&lt;context:component-scan&gt;` 的使用。 一、事务配置 在 SSM 框架中,事务配置是非常重要的,用于确保数据的一致性和安全性。在 XML 配置文件中...

    spring3零配置注解实现Bean定义(包括JSR-250、JSR-330)

    通过使用`&lt;context:component-scan&gt;`标签配合特定的注解(如`@Component`、`@Service`等),可以完全避免XML配置的使用,从而让开发者能够更加专注于业务逻辑的实现。同时,Spring对JSR-250和JSR-330等标准的支持也...

    基于java的企业级应用开发:Spring MVC的核心类和注解.ppt

    在Spring MVC配置文件中,需要添加`&lt;context:component-scan&gt;`元素来指定需要扫描的包,这样Spring才能找到所有的控制器类。如: ```xml &lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi...

    SpringMVC+Hibernate实例

    &lt;context:component-scan base-package="com.bbs"/&gt; &lt;!--注解支持--&gt; &lt;mvc:annotation-driven/&gt; &lt;!--视图解析--&gt; &lt;bean id="viewResolver" class="org.springframework.web.servlet.view....

    springMVC技术概述

    配置使用注解的Handler和Service等等使用&lt;context:component-scan&gt; 不过springBoot已经省略了这些配置 常用注解:@Controller @RestController(Controller+ResponseBody) @Service @Transactional @Mapper @...

Global site tag (gtag.js) - Google Analytics