• SpringIOC——scan()


    闲时研究一下spring源码,一点一点的来。spring版本:5.2.4

    一、构建spring源码环境

    ① spring的源码在github中,右上角fork一个分支到自己的github,然后直接git clone拉代码到本地。

    ② 改阿里云镜像

    // build.gradle和settings.gradle文件中repositories下加入镜像,放到首位
    maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }

    ③ 导入gradle项目到idea中 

    PS:我下载的最新源码默认Gradle5.6.4,但是本地idea2018.1版本不兼容,建议下载最新版idea,然后破解

    第一次构建spring源码环境,发现源码中有好多测试案例,有点惭愧平时工作中很少写测试案例。

    二、IOC容器初始化的过程

    选取SpringBoot默认启动类AnnotationConfigApplicationContext作为研究对象。

    取对应测试案例类AnnotationConfigApplicationContextTests.java中的一个栗子:

        @Test
        void scanAndRefresh() {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
            context.scan("org.springframework.context.annotation6");
            context.refresh();
    
            context.getBean(uncapitalize(ConfigForScanning.class.getSimpleName()));
            context.getBean("testBean"); // contributed by ConfigForScanning
            context.getBean(uncapitalize(ComponentForScanning.class.getSimpleName()));
            context.getBean(uncapitalize(Jsr330NamedForScanning.class.getSimpleName()));
            Map<String, Object> beans = context.getBeansWithAnnotation(Configuration.class);
            assertThat(beans).hasSize(1);
        }
    
    

    1、AnnotationConfigApplicationContex Context = new AnnotationConfigApplication();

       /* AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();*/
    
        //初始化reader,手动装配reader.register(classes),reader.registry = this
        //初始化scannner,自动装配scanner.scan(packages),scanner.registry = this
        public AnnotationConfigApplicationContext() {
            this.reader = new AnnotatedBeanDefinitionReader(this);
            this.scanner = new ClassPathBeanDefinitionScanner(this);
        }
        //父类初始化BeanFactory,IOC容器实质:DefaultListableBeanFactory
        public GenericApplicationContext() {
            this.beanFactory = new DefaultListableBeanFactory();
        }
        //初始化一个资源配置器, new PathMatchingResourcePatternResolver
        public AbstractApplicationContext() { 
            this.resourcePatternResolver = getResourcePatternResolver(); 
        } 

    2、context.scan("org.springframework.context.annotation6"):自动装配指定路径下的bean

      /* context.scan("org.springframework.context.annotation6"); */
    
      /* AnnotationConfigApplicationContext.java */
        public void scan(String... basePackages) {
            Assert.notEmpty(basePackages, "At least one base package must be specified");
            this.scanner.scan(basePackages);
        }
      /* ClassPathBeanDefinitionScanner.java */
        public int scan(String... basePackages) {
            int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
            //自动扫描basePackages下的bean,并装载
            doScan(basePackages);
    
            // 注册注解有关规范的处理器
            if (this.includeAnnotationConfig) {
                AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
            }
            //返回本次自动装配bean的数量
            return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
        }

     doScan(basePackages):

    /* org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java */
        protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
            Assert.notEmpty(basePackages, "At least one base package must be specified");
            Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
            for (String basePackage : basePackages) {
                //将指定basePackage下每个class初始化一个对应BeanDefinition实例,返回实例的集合
                Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
                for (BeanDefinition candidate : candidates) {
                    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                    //默认scopeMetadata.scopeName = singleton 对应Scope注解的value
                    //默认scopeMetadate.scopeProxyMode = no   对应Scope注解的proxyMode
                    candidate.setScope(scopeMetadata.getScopeName());
                    //此时beandefinition只有三个属性beanClass scope metedata
                    //beanName生成器根据注解中value生成beanName,value为空则根据beanClass生成beanName
                    //首字母+第二字母都是大写字母:直接返回例如AA.class beanName = AA
                    //其他首字母变小写例如Aa.class beanName = aa
                    String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                    if (candidate instanceof AbstractBeanDefinition) {
                        //设置一些默认属性
                        //autowireMode = 0
                        //dependencyCheck = 0
                        //initMethodName = 0
                        //enforceInitMethode = false
                        //destroyMethodName = null
                        //enforceDestroyMethod = false
                        //beanName简单校验正则校验,一般beandefinition.autowiredCandidate = true;
                        postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                    }
                    if (candidate instanceof AnnotatedBeanDefinition) {
                        //从metadate中获取并设置一些通用属性
                        //lazyinit:取自lazy注解value,默认null
                        //primary:有primary注解true,不注解默认false
                        //dependsOn:取自dependsOn注解value,默认null
                        //role:取自role注解value,默认0
                        //description:取自description注解value,默认null
                        AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                    }
                    if (checkCandidate(beanName, candidate)) {
                        //BeanDefintionHolder={beanName = "",beanDefintion = "",aliases = ""}
                        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                        //根据scopeMetadate.scopeProxyMode属性决定
                        //ScopedProxyMode.DEFAULT/NO:不创建代理类
                        //ScopedProxyMode.INTERFACES:JDK动态代理创建代理类
                        //ScopedProxyMode.TARGET_CLASS:CGLib创建代理类
                        //如果需要生成代理类,会registerBeanDefinition(targetBean,beanfactory)
                        //下面就是registerBeanDefinition(proxyBean,beanfactory)
                        definitionHolder =
                                AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                        beanDefinitions.add(definitionHolder);
                        registerBeanDefinition(definitionHolder, this.registry);
                    }
                }
            }
            return beanDefinitions;
        }

    Set<BeanDefinition> candidates = findCandidateComponents(basePackage):读入对应package下class文件

    /* org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java */
        private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
            Set<BeanDefinition> candidates = new LinkedHashSet<>();
            try {
                //packageSearchPath = classpath*:basePackage/**/*.class
                String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                        resolveBasePackage(basePackage) + '/' + this.resourcePattern;
                Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
                boolean traceEnabled = logger.isTraceEnabled();
                boolean debugEnabled = logger.isDebugEnabled();
                //resources:
                //D:/myGItHub/spring-framework/spring-context/build/classes/java/test/org/springframework/context/annotation6/ComponentForScanning.class
                for (Resource resource : resources) {
                    if (traceEnabled) {
                        logger.trace("Scanning " + resource);
                    }
                    if (resource.isReadable()) {
                        try {
                            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                            //excludeFilters:过滤器,符合excludeFilters条件的,返回false,不生成BeanDefinition,不初始化bean
                            //includeFilters:过滤器,符合includeFilters条件的,返回true,生成BeanDefinition,初始化bean,
                            //另includeFilters:默认包含三个注解,常见的@Component、
                            //不常见的:
                            //@ManagedBean : javax.annotation.ManagedBean
                            //@Named : javax.inject.Named
                            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;
        }
    registerBeanDefinition(definitionHolder, this.registry);注册beandefinition到beanfactory的容器中
    /* org/springframework/beans/factory/support/DefaultListableBeanFactory.java:901 */
        public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                throws BeanDefinitionStoreException {
    
            Assert.hasText(beanName, "Bean name must not be empty");
            Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    
            if (beanDefinition instanceof AbstractBeanDefinition) {
                try {
                    //beandefinition校验
                    //① 不能将工厂方法和容器生成方法重写结合起来用,factory必须创建具体实例
                    //② beanClass instanceof Class时,校验重写与重载方法
                    ((AbstractBeanDefinition) beanDefinition).validate();
                }
                catch (BeanDefinitionValidationException ex) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                            "Validation of bean definition failed", ex);
                }
            }
    
            BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
            //beandefinition已经存在时
            if (existingDefinition != null) {
                if (!isAllowBeanDefinitionOverriding()) {
                    //如果不允许覆盖,抛出异常
                    throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
                }
                else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                    //role有三种角色 =0:application =1:support =2:infrastructure
                    //newbean角色高于oldbean时log
                    // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                    if (logger.isInfoEnabled()) {
                        logger.info("Overriding user-defined bean definition for bean '" + beanName +
                                "' with a framework-generated bean definition: replacing [" +
                                existingDefinition + "] with [" + beanDefinition + "]");
                    }
                }
                else if (!beanDefinition.equals(existingDefinition)) {
                    //newbean = oldbean log
                    if (logger.isDebugEnabled()) {
                        logger.debug("Overriding bean definition for bean '" + beanName +
                                "' with a different definition: replacing [" + existingDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                else {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Overriding bean definition for bean '" + beanName +
                                "' with an equivalent definition: replacing [" + existingDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                //newbean覆盖oldbean
                this.beanDefinitionMap.put(beanName, beanDefinition);
            }
            //beandefinition不存在
            else {
                if (hasBeanCreationStarted()) {
                    // Cannot modify startup-time collection elements anymore (for stable iteration)
                    //已经有bean被实例化的情况下refresh()或getBean()之后
                    //再进行bean注册(register/scan)操作,无法判断多线程还是单线程,加锁规避多线程场景
                    synchronized (this.beanDefinitionMap) {
                        //bean加入到beanfactory的bean容器beandefinitionMap中,
                        //beanDefinitionMap是ConcurrentHashMap类型put操作是线程安全的
                        //但beandefinitionNames是ArrayList类型add操作时非线程安全的
                        this.beanDefinitionMap.put(beanName, beanDefinition);
                        //既然用到了写时复制策略为什么不用CopyOnWriteArrayList
                        //① 应该是性能需求吧,写时复制会导致内存消耗
                        //② 这里的写时复制策略主要是规避fast-fail,实现fast-safe
                        List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                        updatedDefinitions.addAll(this.beanDefinitionNames);
                        updatedDefinitions.add(beanName);
                        this.beanDefinitionNames = updatedDefinitions;
                        //删除已创建单例的beanName的容器ManualSingletonName中的beanName
                        removeManualSingletonName(beanName);
                    }
                }
                else {
                    // Still in startup registration phase
                    //初次启动容器时单线程
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    this.beanDefinitionNames.add(beanName);
                    removeManualSingletonName(beanName);
                }
                this.frozenBeanDefinitionNames = null;
            }
    
            if (existingDefinition != null || containsSingleton(beanName)) {
                //重新设置相关的beandefinition  子类等
                resetBeanDefinition(beanName);
            }
        }

     

  • 相关阅读:
    Postgresql HStore 插件试用小结
    postgres-xl 安装与部署 【异常处理】ERROR: could not open file (null)/STDIN_***_0 for write, No such file or directory
    GPDB 5.x PSQL Quick Reference
    postgresql 数据库schema 复制
    hive 打印日志
    gp与 pg 查询进程
    jquery table 发送两次请求 解惑
    python 字符串拼接效率打脸帖
    postgresql 日期类型处理实践
    IBM Rational Rose软件下载以及全破解方法
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12364643.html
Copyright © 2020-2023  润新知