zoukankan      html  css  js  c++  java
  • Spring 注解原理(一)组件注册

    Spring 注解原理(一)组件注册

    Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)

    当我们需要使用 Spring 提供的注解开发时,必须在 Spring 容器中声明相关的组件。如 @Autowired 必须注册 AutowiredAnnotationBeanPostProcessor 组件,如果每个组件都需要手动注册未免太麻烦了吧,所以 Spring 为我们提供了自动注入这些组件的方式。<context:annotation-config/> 标签就是专门做这个事的,对应的工具类也是 AnnotationConfigUtils。

    常用注解对应的组件如下:

    序号 组件 功能
    1 AnnotationAwareOrderComparator 排序用,@Order @Priority
    2 ContextAnnotationAutowireCandidateResolver 判断一个给定的对象是否可以注入 @Qualifier @Value
    3 ConfigurationClassPostProcessor @Configuration
    4 AutowiredAnnotationBeanPostProcessor @Autowired
    5 RequiredAnnotationBeanPostProcessor @Required
    6 CommonAnnotationBeanPostProcessor @Resource、@PostConstruct、@PreDestroy
    7 PersistenceAnnotationBeanPostProcessor @PersistenceContext
    8 EventListenerMethodProcessor @EventListener
    9 DefaultEventListenerFactory @EventListener

    一、xml 配置 context:annotation-config/

    在 Spring 的源码中搜索 annotation-config 关键字,找到 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());
        }
    }
    

    annotation-config 对应的解析器为 AnnotationConfigBeanDefinitionParser,查看其源码发现

    public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {
        @Override
        public BeanDefinition parse(Element element, ParserContext parserContext) {
            Object source = parserContext.extractSource(element);
            // 注册 annotation-config 注解驱动相关的组件
            Set<BeanDefinitionHolder> processorDefinitions =
                    AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
            return null;
        }
    }
    

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

    二、注解配置 AnnotatedBeanDefinitionReader

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
    

    可以看到注解的配置的类也调用了 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry) 方法。

    三、AnnotationConfigUtils

    registerAnnotationConfigProcessors 中注册了许多相关的组件。

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
                BeanDefinitionRegistry registry, Object source) {
    
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            // 1. 排序用,解析 @Order @Priority 注解或 PriorityOrdered Ordered 接口
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            // 2. 判断一个给定的对象是否可以注入 @Qualifier @Value
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }
    
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
    
        // 3. @Configuration -> ConfigurationClassPostProcessor
        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));
        }
        // 4. @Autowired -> 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));
        }
        // 5. @Required -> 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));
        }
    
        // 6. @Resource、@PostConstruct、@PreDestroy -> 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));
        }
    
        // 7. @Persistence -> 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( ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
    
        // 8. @Persistence -> EventListenerMethodProcessor
        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));
        }
        // 9. @EventListener -> DefaultEventListenerFactory
        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;
    }
    

    参考:

    1. 《<context:annotation-config/>自动扫描标签详解》:https://www.jianshu.com/p/89f55286cf21

    每天用心记录一点点。内容也许不重要,但习惯很重要!

  • 相关阅读:
    Unable to find required classes (javax.activation.DataHandler and javax.mail.internet.MimeMultipart)
    The type javax.xml.rpc.ServiceException cannot be resolved.It is indirectly
    java 调用webservice (asmx) 客户端开发示例
    CXF动态客户端如何优化JaxWsDynamicClientFactory.createClient -- 慢
    telnet测试端口是否正常打开
    Java 数组 可变长参数 实例
    java数组的声明由几种方式
    Java中包、类、方法、属性、常量的命名规则
    web开发性能优化---安全篇
    linux路由服务
  • 原文地址:https://www.cnblogs.com/binarylei/p/10426087.html
Copyright © 2011-2022 走看看