zoukankan      html  css  js  c++  java
  • spring context:component-scan

    <context:component-scan base-package="com.zhuguang.jack" <!-- 扫描的基本包路径 -->
        annotation-config="true" <!-- 是否激活属性注入注解 -->
        name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator"  <!-- Bean的ID策略生成器 -->
        resource-pattern="**/*.class" <!-- 对资源进行筛选的正则表达式,这边是个大的范畴,具体细分在include-filter与exclude-filter中进行 -->
        scope-resolver="org.springframework.context.annotation.AnnotationScopeMetadataResolver" <!-- scope解析器 ,与scoped-proxy只能同时配置一个 -->
        scoped-proxy="no" <!-- scope代理,与scope-resolver只能同时配置一个 -->
        use-default-filters="false" <!-- 是否使用默认的过滤器,默认值true -->
        >
        <!-- 注意:若使用include-filter去定制扫描内容,要在use-default-filters="false"的情况下,不然会“失效”,被默认的过滤机制所覆盖 -->
        <!-- annotation是对注解进行扫描 ,有这个注解的才会扫描实例化-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
        <!-- assignable是对类或接口进行扫描 ,实现这个接口的才会扫描实例化-->
        <context:include-filter type="assignable" expression="com.wjx.betalot.performer.Performer"/>
        <context:include-filter type="assignable" expression="com.wjx.betalot.performer.impl.Sonnet"/>
        <context:exclude-filter type="regex" expression=".controller.*"/>
        <!-- 注意:在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除,
    有Controller注解的排除, -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="assignable" expression="com.wjx.betalot.performer.impl.RainPoem"/>
        <context:exclude-filter type="regex" expression=".service.*"/>
    </context:component-scan>
    public BeanDefinition parse(Element element, ParserContext parserContext) {
            String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);   //[com.zhuguang.jack]
     
            ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);  //扫描器
            Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
            registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
    
            return null;
        }
    protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
            XmlReaderContext readerContext = parserContext.getReaderContext();   //XmlReaderContext@704deff2
            boolean useDefaultFilters = true;
            if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
                useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));   //默认过滤器
            }
            ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters);   //扫描器
            return scanner;
        }
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
            for (String basePackage : basePackages) {
                Set<BeanDefinition> candidates = findCandidateComponents(basePackage);    // [[AnnotationServiceImpl];], [CommonController]; ]],
                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);   //往bean定义里面设置属性,setLazyInit,setAutowireMode,setDependencyCheck,setInitMethodName,setEnforceInitMethod,setDestroyMethodName,setEnforceDestroyMethod都设置默认值,
                    }
                    if (candidate instanceof AnnotatedBeanDefinition) {
                        AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);    //往bean定义里面设置属性,是否有Lazy,Primary,DependsOn,Role,Description注解,如果有就设置到bean定义中去。
                    }
                    if (checkCandidate(beanName, candidate)) {
                        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);   //把BeanDefinition 变成BeanDefinitionHolder,
                        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);  //
                        beanDefinitions.add(definitionHolder);
                        registerBeanDefinition(definitionHolder, this.registry);   //注册到spring容器中,
                    }
                }
            }
            return beanDefinitions;
        }
    public Set<BeanDefinition> findCandidateComponents(String basePackage) {
            try {
                String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                        resolveBasePackage(basePackage) + "/" + this.resourcePattern;  //classpath*:com/zhuguang/jack/**/*.class找到所有的。class文件,
                Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);     //[file [E:AnnotationServiceImpl.class], file [E:CommonController.class], file [E:CommonMapper.class], file [E:ConsultConfigArea.class], file [E:ConsultContent.class], file [E:MyService.class], file [E:Test2.class], file [E:User.class]]
                for (Resource resource : resources) {
                    if (isCandidateComponent(metadataReader) && resource.isReadable()) {   //没有条件注解,就进来,没有注解的不进来。有@Component注解的才进来,
                        try {
                            MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);  //AnnotationMetadata里面封装了这个类的一些基本信息,类里面有哪些方法,方法上面有哪些注解,类上面有哪些注解,
                            if (isCandidateComponent(metadataReader)) {//!(this.isInterface || this.isAbstract)  &&  (this.enclosingClassName == null || this.independentInnerClass);   不是接口不是抽象类就进来,CommonMapper是一个接口不进来,
                                ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                                sbd.setResource(resource);
                                sbd.setSource(resource);
                                if (isCandidateComponent(sbd)) {
                                    candidates.add(sbd);
                                }
                                else {
                                }
                            }
                        }
                    }
                }
            }
            return candidates;
        }
    public MetadataReader getMetadataReader(Resource resource) throws IOException {
        return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
    }
    SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
            InputStream is = new BufferedInputStream(resource.getInputStream());//文件流,
            ClassReader classReader;
            classReader = new ClassReader(is);
    
            AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
            classReader.accept(visitor, ClassReader.SKIP_DEBUG);
    
            this.annotationMetadata = visitor;
            this.classMetadata = visitor;
            this.resource = resource;
    }
    protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {  //metadataReader是类的元数据信息,
            for (TypeFilter tf : this.excludeFilters) {
                if (tf.match(metadataReader, this.metadataReaderFactory)) {
                    return false;
                }
            }
            for (TypeFilter tf : this.includeFilters) {//interface org.springframework.stereotype.Component,interface javax.inject.Named。有@Component注解的才进来,
                if (tf.match(metadataReader, this.metadataReaderFactory)) {
                    return isConditionMatch(metadataReader);
                }
            }
            return false;
        }
    public Resource[] getResources(String locationPattern) throws IOException {
            if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
                if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
                    return findPathMatchingResources(locationPattern);
                }
            }
        }
    protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
            String rootDirPath = determineRootDir(locationPattern);   //classpath*:com/zhuguang/jack/
            String subPattern = locationPattern.substring(rootDirPath.length());   //**/*.class
            Resource[] rootDirResources = getResources(rootDirPath);     //返回[URL [file:/E:/Code/AAAAA/AAAAA/2019326/2/spring-source-web-master-aop/target/classes/com/zhuguang/jack/]]
            Set<Resource> result = new LinkedHashSet<Resource>(16);
            for (Resource rootDirResource : rootDirResources) {
                rootDirResource = resolveRootDirResource(rootDirResource);     //返回[URL [file:/E:/Code/AAAAA/AAAAA/2019326/2/spring-source-web-master-aop/target/classes/com/zhuguang/jack/]]
                if (isJarResource(rootDirResource)) {
                    result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));
                }
                else if (rootDirResource.getURL().getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
                    result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirResource, subPattern, getPathMatcher()));
                }
                else {
                    result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
                }
            }
            return result.toArray(new Resource[result.size()]);    //[file [E:AnnotationServiceImpl.class], file [E:CommonController.class], file [E:CommonMapper.class], file [E:ConsultConfigArea.class], file [E:ConsultContent.class], file [E:MyService.class], file [E:Test2.class], file [E:User.class]]
        }
    public Resource[] getResources(String locationPattern) throws IOException {
                else {
                    return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
                }
            }
        }
    
    protected Resource[] findAllClassPathResources(String location) throws IOException {
            Enumeration<URL> resourceUrls = getClassLoader().getResources(path);   //AppClassLoader,返回[sun.misc.CompoundEnumeration@b83a9be, java.net.URLClassLoader$3@2609b277]
            Set<Resource> result = new LinkedHashSet<Resource>(16);
            while (resourceUrls.hasMoreElements()) {
                URL url = resourceUrls.nextElement();
                result.add(convertClassLoaderURL(url));
            }
            return result.toArray(new Resource[result.size()]);   //返回[URL [file:/E:/Code/AAAAA/AAAAA/2019326/2/spring-source-web-master-aop/target/classes/com/zhuguang/jack/]]
        }
    public Enumeration<URL> getResources(String name) throws IOException {
            @SuppressWarnings("unchecked")
            Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
            if (parent != null) {
                tmp[0] = parent.getResources(name);  //ExtClassLoader
            } else {
                tmp[0] = getBootstrapResources(name);
            }
            tmp[1] = findResources(name);
    
            return new CompoundEnumeration<>(tmp);
        }
    private static Enumeration<URL> getBootstrapResources(String name)   {
            final Enumeration<Resource> e = getBootstrapClassPath().getResources(name);   //sun.misc.URLClassPath@28d18df5
            return new Enumeration<URL> () {
                public URL nextElement() {
                    return e.nextElement().getURL();
                }
                public boolean hasMoreElements() {
                    return e.hasMoreElements();
                }
            }
        }
  • 相关阅读:
    centos 安装nginx + 多个tomcat负载均衡
    centos 安装redis2.8.9
    centos下彻底删除mysql
    List的深度序列化Demo
    session失效刷新后登录页面嵌入在iframe中的解决办法
    Unable to execute dex: Multiple dex files define 解决方法
    Android运行时异常“Binary XML file line # : Error inflating class”
    在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案
    ViewStub的使用示例
    android中导入低版本project可能会遇到的编译问题
  • 原文地址:https://www.cnblogs.com/yaowen/p/11850729.html
Copyright © 2011-2022 走看看