美文网首页
<context:annotation-config/>自动扫描

<context:annotation-config/>自动扫描

作者: 多喝水JS | 来源:发表于2017-03-28 18:21 被阅读2436次

    当我们需要使用BeanPostProcessor时,直接在Spring配置文件中定义这些Bean显得比较笨拙,例如:使用@Autowired注解,必须事先在Spring容器中声明AutowiredAnnotationBeanPostProcessor的Bean:
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor "/>
      使用 @Required注解,就必须声明RequiredAnnotationBeanPostProcessor的Bean:
    <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
      类似地,使用@Resource、@PostConstruct、@PreDestroy等注解就必须声明 CommonAnnotationBeanPostProcessor;使用@PersistenceContext注解,就必须声明 PersistenceAnnotationBeanPostProcessor的Bean。
      这样的声明未免太麻烦了吧,所以Spring为我们提供了一种极为方便注册这些BeanPostProcessor的方式,即使用<context:annotation- config/>隐式地向 Spring容器注册AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor以及PersistenceAnnotationBeanPostProcessor这4个BeanPostProcessor。如下:
    <context:annotation-config/>

    官方文档的说明:

    As always, you can register them as individual bean definitions, but they can also be implicitly registered by including the following tag in an XML-based Spring configuration (notice the inclusion of the context namespace):
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:annotation-config/>
    
    </beans>
    

     那么<context:annotation-config/> 这个标签时何时注入这些BeanPostProcessor的呢?

    下面进行源码分析

    在Spring容器解析配置文件中时,会加载beans标签中配置的URL,如下图

    <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
                    xsi:schemaLocation="http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context-3.1.xsd
                                " >
    

    (1)根据beans标签中配置的xsi:schemaLocation的URL到spring.handlers文件中,找到对应的NamespaceHandler

    Paste_Image.png

    比如我上面的是http://www.springframework.org/schema/context
    那么将对应spring.handlers文件中的ContextNamespaceHandler

    http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
    

    (2)由上面的可见,根据这个http://www.springframework.org/schema/context可以找到ContextNamespaceHandler类,这个类是干啥用的呢?

    public class ContextNamespaceHandler extends NamespaceHandlerSupport {
    
        @Override
        public void init() {
            registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
            registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
            registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
            registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
            registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
            registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
            registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
            registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
        }
    
    }
    

    就一个方法,在唯一一个方法中,可以看到一些很熟悉的单词。没错,它的作用就是创建这些标签所对应的解析类。
    何为解析类?也就是所有的自定义命名空间(像mvc,context等)下的标签解析都是由BeanDefinitionParser接口的子类来完成的。
    可以看到nnotation-config"的解析类是 AnnotationConfigBeanDefinitionParser
    ,那么进入这个类中看它是如何解析这个标签的
    (3)
    解析的方法是在parse方法中

    @Override
        public BeanDefinition parse(Element element, ParserContext parserContext) {
            Object source = parserContext.extractSource(element);
    
            // Obtain bean definitions for all relevant BeanPostProcessors.
            Set<BeanDefinitionHolder> processorDefinitions =
    //这里将注册获取到所有相关BeanPostProcessors的bean定义。    所以解析过程是在这个方法中
                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;
        }
    
    

    根据上面代码可以看出真正的解析是在AnnotationConfigUtils.registerAnnotationConfigProcessors()方法中进行的
    进去这个方法看看

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
                BeanDefinitionRegistry registry, 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<BeanDefinitionHolder>(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));
            }
    //实例化AutowiredAnnotationBeanPostProcessor
            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));
            }
    //实例化RequiredAnnotationBeanPostProcessor
            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));
            }
    
            // 实例化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));
            }
    
            // 实例化PersistenceAnnotationBeanPostProcessor.
            if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition();
                try {
                    def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                            AnnotationConfigUtils.class.getClassLoader()));
                }
                catch (ClassNotFoundException ex) {
                    throw new IllegalStateException(
                            "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
                }
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
            }
    
            if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
            }
            if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
                RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
                def.setSource(source);
                beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
            }
    
            return beanDefs;
        }
    
    

    代码可以看到,分别注册了AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor以及PersistenceAnnotationBeanPostProcessor这4个BeanPostProcessor。

    后记

    这是我自己看源码总结的,错误之处请帮忙指出,大家一起进步。

    [朝阳区尼克杨]
    转载请注明原创出处,谢谢啦!

    相关文章

      网友评论

          本文标题:<context:annotation-config/>自动扫描

          本文链接:https://www.haomeiwen.com/subject/ysfsottx.html