spring context:component-scan与&context:annotation-config的区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangjun5159/article/details/82431271

前言

< context:annotation-config/>

用来注册几个常用的BeanPostProcessor,常见的BeanPostProcessor有ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor,他们主要用来解析@Autowired@required@Configuration@Component,简单来说,BeanPostProcessor是让这些注解生效的。

<context:component-scan/>

包含了< context:annotation-config/> 的作用,同时还注册base-package下的注解类。
如果理解了上述所说,那么也就懂得,no bean named springsessionrepositoryfilter is defined ,就是因为没配置此两项之一。

解读源码

为了更好的理解这两个标签,有必要阅读源码。

< context:annotation-config/>源码

首先找到ContextNamespaceHandler,它用来解析context命名空间下的元素,看一下继承层次图
这里写图片描述

public class ContextNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        //只保留重要的两句
        registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
        registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());

    }

}

annotation-config对应AnnotationConfigBeanDefinitionParser
主要看parse方法,

public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {

    @Override
    @Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        Object source = parserContext.extractSource(element);

        // 获取所有与BeanPostProcessors有关的bean定义.
        Set<BeanDefinitionHolder> processorDefinitions =
                AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);



        return null;
    }

}

AnnotationConfigUtils.registerAnnotationConfigProcessors 中获取所有BeanPostProcessor 的bean

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }

        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);

        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        //...

        return beanDefs;
    }

这里用到了CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAMEAUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME 等几个常量,在此列了一个表

常量 对应的BeanPostProcessor 对应的注解
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME ConfigurationClassPostProcessor @Configuration
AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME AutowiredAnnotationBeanPostProcessor @AutoWired
REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME RequiredAnnotationBeanPostProcessor @Required
COMMON_ANNOTATION_PROCESSOR_BEAN_NAME CommonAnnotationBeanPostProcessor @javax.annotation.PostConstruct、@javax.annotation.PreDestroy

等等,还有几个,就不列了。

<context:component-scan/>源码

类似的,我们看ComponentScanBeanDefinitionParser 的parse方法

public BeanDefinition parse(Element element, ParserContext parserContext) {
        String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
        basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
        String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
                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;
    }

简单来说,就是扫描属性base-package指定包下的类,然后注册,那重点就在registerComponents方法了。

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);
    }

可以看出此方法就做了两件事,一是注册base-package下的类,二是调用AnnotationConfigUtils.registerAnnotationConfigProcessors 注册BeanPostProcessor,跟< context:annotation-config/>一模一样。到此就真相大白了。

总结

再来总结一遍,

  • < context:annotation-config/>注册了常用的BeanPostProcessor,而这些BeanPostProcessor 就是让常用注解(@AutoWired、@Configuration)生效。

  • <context:component-scan/> 做了< context:annotation-config/>所有做的事,除此之外,还扫描注册base-package下的类。

  • 综上所述,两者只能留其一。

猜你喜欢

转载自blog.csdn.net/wangjun5159/article/details/82431271
今日推荐