zoukankan      html  css  js  c++  java
  • 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);
            }
        }

     

  • 相关阅读:
    【BZOJ3926】诸神眷顾的幻想乡 【广义后缀自动机】
    【BZOJ2780】Sevenk Love Oimaster【广义后缀自动机】
    【BZOJ3227】串【广义后缀自动机】
    【CodeForces
    【BZOJ3238】差异【后缀自动机+dp】
    【BZOJ4566】找相同字符【后缀自动机】
    【BZOJ3998】弦论 【后缀自动机】
    【poj1743】Musical Theme 【后缀自动机】
    【SPOJ
    【SPOJ
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12364643.html
Copyright © 2011-2022 走看看