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);
        }
    }

 

posted on 2020-02-25 23:31  FFStayF  阅读(363)  评论(0编辑  收藏  举报