zoukankan      html  css  js  c++  java
  • Spring源码解析-基于注解依赖注入

    在spring2.5版本提供了注解的依赖注入功能,可以减少对xml配置。

    主要使用的是

    AnnotationConfigApplicationContext: 一个注解配置上下文
    AutowiredAnnotationBeanPostProcessor: spring提供的用于这一目的的BeanPostProcessor实现,用来检查当前对象是否有@Autowired标注的依赖注入。

    项目中除了使用@Autowired之外,还可以选择JSR250的一些注解例如@Resource大致和@Autowired相同。
    CommonAnnotationBeanPostProcessor:JSR250也需要BeanPostProcessor,spring实现类了。
    在spring配置文件中添加<context:annotation-config/>可以将这些processor添加到spring容器中。
    另外使用注解的方式还需要一个classpath-scanning功能,使用这一功能只需要在配置文件中添加<context:component-scan base-package='com.xx.xx'>
    @Component注解使用太宽泛,细分了@Controller,@Service等标注。

    简单示例
    @Component
    public class AnnotationDemo {
    
        public void printInfo(){
            System.out.println(this.getClass());
        }
    }
    
    @Component
    public class AnnotationDemo2 {
    
        public void printInfo(){
            System.out.println(this.getClass());
        }
    }
    

    测试类

    @Test
        public void testAnnotationInject(){
           ApplicationContext context = new AnnotationConfigApplicationContext("org.lzyer.test");
           //指定某些类
            //ApplicationContext context = new AnnotationConfigApplicationContext(AnnotationDemo.class,AnnotationDemo2.class);
            AnnotationDemo ad = context.getBean(AnnotationDemo.class);
            AnnotationDemo2 ad2 = context.getBean(AnnotationDemo2.class);
            ad.printInfo();
            ad2.printInfo();
        }
    

    方式一为加载包下带注解的类。方式二是指定某些类。

    运行结果:

    class org.lzyer.test.AnnotationDemo
    class org.lzyer.test.AnnotationDemo2

    注入流程

        /**
         * Create a new AnnotationConfigApplicationContext, scanning for bean definitions
         * in the given packages and automatically refreshing the context.
         * @param basePackages the packages to check for annotated classes
         */
        public AnnotationConfigApplicationContext(String... basePackages) {
            this();
            scan(basePackages);//扫描包
            refresh();//调用AbstractApplicationContext中的refresh方法
        }
    /**
         * Perform a scan within the specified base packages.
         * @param basePackages the packages to check for annotated classes
         * @return number of beans registered
         */
        public int scan(String... basePackages) {
            int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
    
            doScan(basePackages);//扫描
    
            // Register annotation config processors, if necessary.
            if (this.includeAnnotationConfig) {
                AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
            }
    
            return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
        }
    /**
         * 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);//注册beandefinition
                    }
                }
            }
            return beanDefinitions;
        }
    /**
         * Scan the class path for candidate components.
         * @param basePackage the package to check for annotated classes
         * @return a corresponding Set of autodetected bean definitions
         */
        public Set<BeanDefinition> findCandidateComponents(String basePackage) {
            Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
            try {
                String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                        resolveBasePackage(basePackage) + "/" + this.resourcePattern;//补充路径
                Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
                boolean traceEnabled = logger.isTraceEnabled();
                boolean debugEnabled = logger.isDebugEnabled();
                for (Resource resource : resources) {//遍历Resource
                    if (traceEnabled) {
                        logger.trace("Scanning " + resource);
                    }
                    if (resource.isReadable()) {
                        try {//通过asm获取class,暂且不研究asm
                            MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                            if (isCandidateComponent(metadataReader)) {//判断是否为候选组件
                                ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                                sbd.setResource(resource);
                                sbd.setSource(resource);
                                if (isCandidateComponent(sbd)) {//判断是否为候选组件
                                    if (debugEnabled) {
                                        logger.debug("Identified candidate component class: " + resource);
                                    }
                                    candidates.add(sbd);//添加候选组件
                                }
                                else {
                                    if (debugEnabled) {
                                        logger.debug("Ignored because not a concrete top-level class: " + resource);
                                    }
                                }
                            }
                            else {
                                if (traceEnabled) {
                                    logger.trace("Ignored because not matching any filter: " + resource);
                                }
                            }
                        }
                        catch (Throwable ex) {
                            throw new BeanDefinitionStoreException(
                                    "Failed to read candidate component class: " + resource, ex);
                        }
                    }
                    else {
                        if (traceEnabled) {
                            logger.trace("Ignored because not readable: " + resource);
                        }
                    }
                }
            }
            catch (IOException ex) {
                throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
            }
            return candidates;
        }

    查看2个判断条件。

    /**
         * Determine whether the given bean definition qualifies as candidate.
         * <p>The default implementation checks whether the class is concrete
         * (i.e. not abstract and not an interface). Can be overridden in subclasses.
         * @param beanDefinition the bean definition to check
         * @return whether the bean definition qualifies as a candidate component
         */
        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
            return (beanDefinition.getMetadata().isConcrete() && beanDefinition.getMetadata().isIndependent());
        }

    进行匹配。

    /**
         * Determine whether the given class does not match any exclude filter
         * and does match at least one include filter.
         * @param metadataReader the ASM ClassReader for the class
         * @return whether the class qualifies as a candidate component
         */
        protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
            for (TypeFilter tf : this.excludeFilters) {
                if (tf.match(metadataReader, this.metadataReaderFactory)) {
                    return false;
                }
            }
            for (TypeFilter tf : this.includeFilters) {
                if (tf.match(metadataReader, this.metadataReaderFactory)) {
                    return isConditionMatch(metadataReader);
                }
            }
            return false;
        }
    @Override
        protected boolean matchSelf(MetadataReader metadataReader) {
            AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
            return metadata.hasAnnotation(this.annotationType.getName()) ||
                    (this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
        }

    查看hasAnnotation和 hasMetaAnnotation方法。

        @Override
        public boolean hasAnnotation(String annotationType) {
            return this.annotationSet.contains(annotationType);
        }
    
        @Override
        public boolean hasMetaAnnotation(String metaAnnotationType) {
            Collection<Set<String>> allMetaTypes = this.metaAnnotationMap.values();
            for (Set<String> metaTypes : allMetaTypes) {
                if (metaTypes.contains(metaAnnotationType)) {
                    return true;
                }
            }
            return false;
        }
    annotationSet包含的是注解,
    metaAnnotationMap的key为注解,value是一个set。




  • 相关阅读:
    Opencv保存摄像头视频&&各种编码器下视频文件占用空间对比
    生活的 tricks
    生活的 tricks
    词汇的积累 —— 反义词、同义词
    词汇的积累 —— 反义词、同义词
    目标跟踪系列十一:Exploiting the Circulant Structure of Tracking-by-detection with Kernels代码思路
    Java中Integer类的方法
    php中 重载(二)
    协方差的意义
    malloc函数具体解释
  • 原文地址:https://www.cnblogs.com/lzeffort/p/7745764.html
Copyright © 2011-2022 走看看