• spring源码分析之<context:component-scan/>vs<annotation-config/>


    1.<context:annotation-config/>

    xsd中说明:

    <xsd:element name="annotation-config">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    Activates various annotations to be detected in bean classes: Spring's @Required and @Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available), JAX-WS's @WebServiceRef (if available), EJB3's @EJB (if available), and JPA's @PersistenceContext and @PersistenceUnit (if available). Alternatively, you may choose to activate the individual BeanPostProcessors for those annotations. Note: This tag does not activate processing of Spring's @Transactional or EJB3's @TransactionAttribute annotation. Consider the use of the <tx:annotation-driven> tag for that purpose.
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    </xsd:element>

    解析发生在在解析xml文件中,解析类为:AnnotationConfigBeanDefinitionParser.java

    public BeanDefinition parse(Element element, ParserContext parserContext) {
            Object source = parserContext.extractSource(element);
    
            // Obtain bean definitions for all relevant BeanPostProcessors.
            Set<BeanDefinitionHolder> processorDefinitions =
                    AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
    
            // Register component for the surrounding <context:annotation-config> element.
            CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
            parserContext.pushContainingComponent(compDefinition);
    
            // Nest the concrete beans in the surrounding component.
            for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
                parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
            }
    
            // Finally register the composite component.
            parserContext.popAndRegisterContainingComponent();
    
            return null;
        }

    2.<context:component-scan/>

    <xsd:element name="component-scan">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    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.
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="include-filter" type="filterType" minOccurs="0" maxOccurs="unbounded">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    Controls which eligible types to include for component scanning.
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    </xsd:element>
    <xsd:element name="exclude-filter" type="filterType" minOccurs="0" maxOccurs="unbounded">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    Controls which eligible types to exclude for component scanning.
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    </xsd:element>
    </xsd:sequence>
    <xsd:attribute name="base-package" type="xsd:string" use="required">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    The comma-separated list of packages to scan for annotated components.
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    </xsd:attribute>
    <xsd:attribute name="resource-pattern" type="xsd:string">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    Controls the class files eligible for component detection. Defaults to "**/*.class", the recommended value.
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    </xsd:attribute>
    <xsd:attribute name="use-default-filters" type="xsd:boolean" default="true">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    Indicates whether automatic detection of classes annotated with @Component, @Repository, @Service, or @Controller should be enabled. Default is "true".
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    </xsd:attribute>
    <xsd:attribute name="annotation-config" type="xsd:boolean" default="true">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    Indicates whether the implicit annotation post-processors should be enabled. Default is "true".
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    </xsd:attribute>
    <xsd:attribute name="name-generator" type="xsd:string">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    The fully-qualified class name of the BeanNameGenerator to be used for naming detected components.
    ]]>
    </xsd:documentation>
    <xsd:appinfo>
    <tool:annotation>
    <tool:expected-type type="java.lang.Class"/>
    <tool:assignable-to type="org.springframework.beans.factory.support.BeanNameGenerator"/>
    </tool:annotation>
    </xsd:appinfo>
    </xsd:annotation>
    </xsd:attribute>
    <xsd:attribute name="scope-resolver" type="xsd:string">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    The fully-qualified class name of the ScopeMetadataResolver to be used for resolving the scope of detected components.
    ]]>
    </xsd:documentation>
    <xsd:appinfo>
    <tool:annotation>
    <tool:expected-type type="java.lang.Class"/>
    <tool:assignable-to type="org.springframework.context.annotation.ScopeMetadataResolver"/>
    </tool:annotation>
    </xsd:appinfo>
    </xsd:annotation>
    </xsd:attribute>
    <xsd:attribute name="scoped-proxy">
    <xsd:annotation>
    <xsd:documentation>
    <![CDATA[
    Indicates whether proxies should be generated for detected components, which may be necessary when using scopes in a proxy-style fashion. Default is to generate no such proxies.
    ]]>
    </xsd:documentation>
    </xsd:annotation>
    <xsd:simpleType>
    <xsd:restriction base="xsd:string">
    <xsd:enumeration value="no"/>
    <xsd:enumeration value="interfaces"/>
    <xsd:enumeration value="targetClass"/>
    </xsd:restriction>
    </xsd:simpleType>
    </xsd:attribute>
    </xsd:complexType>
    </xsd:element>

    注意:红色的一行中,说明<context:component-scan>包含<context:annotation-config>,且<context:annotation-config>的作用是:

    Indicates whether automatic detection of classes annotated with @Component, @Repository, @Service, or @Controller should be enabled.

    而<context:component-scan>解析发生在在解析xml文件中,解析类为:ComponentScanBeanDefinitionParser.java

        public BeanDefinition parse(Element element, ParserContext parserContext) {
            String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    
            // Actually scan for bean definitions and register them.
            ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
            Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
            registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
    
            return null;
        }

    注册过程如下:

    protected void registerComponents(
                XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
    
            Object source = readerContext.extractSource(element);
            CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
    
            for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
                compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
            }
    
            // Register annotation config processors, if necessary.
            boolean annotationConfig = true;
            if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
                annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
            }
            if (annotationConfig) {
                Set<BeanDefinitionHolder> processorDefinitions =
                        AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
                for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
                    compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
                }
            }
    
            readerContext.fireComponentRegistered(compositeDef);
        }

    其中,红色部分是关于<annotation-config>部分的。

  • 相关阅读:
    SpringMVC+Apache Shiro+JPA(hibernate)
    Win7系统上配置使用Intellij Idea 13的SVN插件
    标志一个方法为过时方法
    Java模板引擎 HTTL
    Spring security与shiro
    墨刀 手机app原型工具
    java远程调试(断点)程序/tomcat( eclipse远程调试Tomcat方法)
    结合MongoDB开发LBS应用
    基于LBS的地理位置附近的搜索以及由近及远的排序
    discuz 发布分类信息,能不能设置单版块去掉“发帖子”(默认点发帖后为自定义的默认分类信息模版)
  • 原文地址:https://www.cnblogs.com/davidwang456/p/5646093.html
Copyright © 2020-2023  润新知