• 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;// 这里
        }
  • 相关阅读:
    284.软件体系结构集成开发环境的作用
    Socket编程:邮件客户
    Socket编程:UDP Ping
    Socket编程:Web服务器
    计算机网络面试题总结(网络层)
    零基础黑客入门
    MYSQL的安装和配置(Windows)
    计算机网络面试题(分层概念+数据链路层)
    车载网络入侵检测系统设计
    操作系统知识点
  • 原文地址:https://www.cnblogs.com/zno2/p/4691401.html
Copyright © 2020-2023  润新知