zoukankan      html  css  js  c++  java
  • context:component-scan

    一、介绍

    Scans the classpath for annotated components that will be auto-registered as Spring beans. By default, the Spring-provided @Component, @Repository, @Service, and @Controller stereotypes will be detected. Note: This tag implies the effects of the 'annotation-config' tag, activating @Required, @Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit annotations in the component classes, which is usually desired for autodetected components (without external configuration). Turn off the 'annotation-config' attribute to deactivate this default behavior, for example in order to use custom BeanPostProcessor definitions for handling those annotations. Note: You may use placeholders in package paths, but only resolved against system properties (analogous to resource paths). A component scan results in new bean definition being registered; Spring's PropertyPlaceholderConfigurer will apply to those bean definitions just like to regular bean definitions, but it won't apply to the component scan settings themselves. See javadoc for org.springframework.context.annotation.ComponentScan for information on code-based alternatives to bootstrapping component-scanning.

    • @Component
    • @Repository
    • @Service
    • @Controller
    <xsd:attribute name="base-package" type="xsd:string" use="required">...</xsd:attribute>
    <xsd:attribute name="resource-pattern" type="xsd:string">...</xsd:attribute>
    <xsd:attribute name="use-default-filters" type="xsd:boolean" default="true">...</xsd:attribute>
    <xsd:attribute name="annotation-config" type="xsd:boolean" default="true">...</xsd:attribute>
    <xsd:attribute name="name-generator" type="xsd:string">...</xsd:attribute>
    <xsd:attribute name="scope-resolver" type="xsd:string">...</xsd:attribute>
    <xsd:attribute name="scoped-proxy">...</xsd:attribute>
    <xsd:element name="include-filter" type="filterType" minOccurs="0" maxOccurs="unbounded">...</xsd:element>
    <xsd:element name="exclude-filter" type="filterType" minOccurs="0" maxOccurs="unbounded">...</xsd:element>

    作用:

    自动寻找被特定注解类标识的bean注册到 spring容器

    @Component 是最基本的组件 ,和标签的名字一样 <context:component-scan

    有一个属性是annotation-config 默认值是true ,默认是开启自动注入的。功能同<context:annotation-config /> 无需重复填写。

    back-package 是 扫描的这个文件夹下的,使用* 通配符时,会有扫描所有类包含spring的类,会产生问题

    Caused by: java.lang.IllegalArgumentException: @EnableAsync annotation metadata was not injected
    	at org.springframework.util.Assert.notNull(Assert.java:115)
    	at org.springframework.scheduling.annotation.ProxyAsyncConfiguration.asyncAdvisor(ProxyAsyncConfiguration.java:46)
    	at org.springframework.scheduling.annotation.ProxyAsyncConfiguration$$EnhancerBySpringCGLIB$$74da8fff.CGLIB$asyncAdvisor$0(<generated>)
    	at org.springframework.scheduling.annotation.ProxyAsyncConfiguration$$EnhancerBySpringCGLIB$$74da8fff$$FastClassBySpringCGLIB$$c42525c5.invoke(<generated>)
    	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356)
    	at org.springframework.scheduling.annotation.ProxyAsyncConfiguration$$EnhancerBySpringCGLIB$$74da8fff.asyncAdvisor(<generated>)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:498)
    	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
    	... 43 more

    use-default-filters 是扫描文件夹下的全部

    filterType 有 5个值,点击看明细

    "annotation" indicates an annotation to be present at the type level in target components;
    "assignable" indicates a class (or interface) that the target components are assignable to (extend/implement);
    "aspectj" indicates an AspectJ type pattern expression to be matched by the target components;
    "regex" indicates a regex pattern to be matched by the target components' class names;
    "custom" indicates a custom implementation of the org.springframework.core.type.TypeFilter interface.

    二、用法

    注:a,b为不同package,其下所有类均实现了 ForScan 接口

    import java.util.Arrays;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @ContextConfiguration(locations= {"classpath:spring/root/private-root.xml"})
    @RunWith(SpringJUnit4ClassRunner.class)
    public class ScanTest {
        
        @Autowired
        private ApplicationContext ap;
    
        @Test
        public void test() {
            String[] beanNamesForType = ap.getBeanNamesForType(ForScan.class);
            System.out.println(Arrays.asList(beanNamesForType));
        }
    
    }

     1. regex 排除

    其中 regex 中 的class names 是针对全限定名的正则匹配,比如:

        <context:component-scan base-package="cn.zno.testscan">
            <context:exclude-filter type="regex" expression="cn.zno.testscan.a.*"/>
        </context:component-scan>

    结果:[b1, b2]

        <context:component-scan base-package="cn.zno.testscan">
            <context:exclude-filter type="regex" expression="cn.zno.testscan.a.A1"/>
        </context:component-scan>

    结果:[a2, b1, b2]

     2.regex 只有

        <context:component-scan base-package="cn.zno.testscan" use-default-filters="false">
            <context:include-filter type="regex" expression="cn.zno.testscan.a.*"/>
        </context:component-scan>

    结果:[a1, a2]

        <context:component-scan base-package="cn.zno.testscan" use-default-filters="false">
            <context:include-filter type="regex" expression="cn.zno.testscan.a.A1"/>
        </context:component-scan>

    结果:[a1]

    3. 多次扫描

    1)分块扫描

        <context:component-scan base-package="cn.zno.testscan.a"></context:component-scan>
        <context:component-scan base-package="cn.zno.testscan.b"></context:component-scan>

    结果:

    [a1, a2, b1, b2]

     2)重复扫描

        <context:component-scan base-package="cn.zno.testscan.a"></context:component-scan>
        <context:component-scan base-package="cn.zno.testscan.a"></context:component-scan>

    结果:

    [a1, a2]

    第二次重复扫描时返回了[] 数组

    4. 多次扫描有何不良影响

    org.springframework.context.annotation.ClassPathBeanDefinitionScanner

        /**
         * Perform a scan within the specified base packages,
         * returning the registered bean definitions.
         * <p>This method does <i>not</i> register an annotation config processor
         * but rather leaves this up to the caller.
         * @param basePackages the packages to check for annotated classes
         * @return set of beans registered if any for tooling registration purposes (never {@code null})
         */
        protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
            Assert.notEmpty(basePackages, "At least one base package must be specified");
            Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
            for (String basePackage : basePackages) {
                Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
                for (BeanDefinition candidate : candidates) {
                    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                    candidate.setScope(scopeMetadata.getScopeName());
                    String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                    if (candidate instanceof AbstractBeanDefinition) {
                        postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                    }
                    if (candidate instanceof AnnotatedBeanDefinition) {
                        AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                    }
                    if (checkCandidate(beanName, candidate)) {
                        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                        beanDefinitions.add(definitionHolder);
                        registerBeanDefinition(definitionHolder, this.registry);
                    }
                }
            }
            return beanDefinitions;// 这里
        }
  • 相关阅读:
    Samba 4.0 RC3 发布
    SymmetricDS 3.1.7 发布,数据同步和复制
    Express.js 3.0 发布,Node.js 的高性能封装
    GIFLIB 5.0.1 发布,C语言的GIF处理库
    jQuery UI 1.9.1 发布
    SVN Access Manager 0.5.5.14 发布 SVN 管理工具
    DynamicReports 3.0.3 发布 Java 报表工具
    HttpComponents HttpClient 4.2.2 GA 发布
    AppCan 2.0 正式发布,推移动应用云服务
    Ruby 2.0 的新功能已经冻结
  • 原文地址:https://www.cnblogs.com/zno2/p/4691401.html
Copyright © 2011-2022 走看看