1. @MapperScan 掃描包流程分析

        共 12628字,需瀏覽 26分鐘

         ·

        2021-06-08 23:46

        以下文章來源于武培軒,回復(fù)資源獲取資料

        前言

        其實(shí)一般不寫這樣的分析的,但是這次呢一是為了記錄下來分析過程,二是給大家分享一下@MapperScan注解掃描包的流程吧。

        提出問題

        @MapperScan("com.fast")掃描的是com.fast這個(gè)包下面的bean是毋庸置疑的,但是包括子包下面的bean嗎?

        疑問案例

        比如com.fast.master.dao,還有com.fast.second.dao這些包下面的bean是否會一起被掃描到?

        分析

        1. 查看MapperScan注解,掃描包主要是這個(gè)@Import({MapperScannerRegistrar.class})
        @Retention(RetentionPolicy.RUNTIME)
        @Target({ElementType.TYPE})
        @Documented
        @Import({MapperScannerRegistrar.class})
        @Repeatable(MapperScans.class)
        public @interface MapperScan {
            String[] value() default {};

            String[] basePackages() default {};
             
            Class<?>[] basePackageClasses() default {};
             
            Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
             
            Class<? extends Annotation> annotationClass() default Annotation.class;
             
            Class<?> markerInterface() default Class.class;
             
            String sqlSessionTemplateRef() default "";
             
            String sqlSessionFactoryRef() default "";
             
            Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
        }
        1. 找到MapperScannerRegistrar.class看實(shí)現(xiàn)過程,就不全貼了,主要是這個(gè)注解這一塊
            void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry) {
                ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
                Optional var10000 = Optional.ofNullable(this.resourceLoader);
                Objects.requireNonNull(scanner);
                var10000.ifPresent(scanner::setResourceLoader);
                Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
                if (!Annotation.class.equals(annotationClass)) {
                    scanner.setAnnotationClass(annotationClass);
                }
                Class<?> markerInterface = annoAttrs.getClass("markerInterface");
                if (!Class.class.equals(markerInterface)) {
                    scanner.setMarkerInterface(markerInterface);
                }
                Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
                if (!BeanNameGenerator.class.equals(generatorClass)) {
                    scanner.setBeanNameGenerator((BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
                }
                Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
                if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
                    scanner.setMapperFactoryBeanClass(mapperFactoryBeanClass);
                }
                scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
                scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
                List<String> basePackages = new ArrayList();
                basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("value")).filter(StringUtils::hasText).collect(Collectors.toList()));
                basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText).collect(Collectors.toList()));
                basePackages.addAll((Collection)Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName).collect(Collectors.toList()));
                scanner.registerFilters();
                scanner.doScan(StringUtils.toStringArray(basePackages));
            }

        這句周圍的是不是很熟悉,就是MapperScan實(shí)現(xiàn)的注解,value,basePackages,basePackageClasses這幾個(gè)

        basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("value")).filter(StringUtils::hasText).collect(Collectors.toList()));
        basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText).collect(Collectors.toList()));
        basePackages.addAll((Collection)Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName).collect(Collectors.toList()));
        scanner.registerFilters();
        scanner.doScan(StringUtils.toStringArray(basePackages));

        從scanner.doScan這句進(jìn)去,這里是開始掃描包的地方

        1. 打開調(diào)用的方法
        private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
                Iterator var3 = beanDefinitions.iterator();

                while(var3.hasNext()) {
                    BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next();
                    GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition();
                    String beanClassName = definition.getBeanClassName();
                    LOGGER.debug(() -> {
                        return "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + "' mapperInterface";
                    });
                    definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
                    definition.setBeanClass(this.mapperFactoryBeanClass);
                    definition.getPropertyValues().add("addToConfig", this.addToConfig);
                    boolean explicitFactoryUsed = false;
                    if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
                        definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
                        explicitFactoryUsed = true;
                    } else if (this.sqlSessionFactory != null) {
                        definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
                        explicitFactoryUsed = true;
                    }
             
                    if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
                        if (explicitFactoryUsed) {
                            LOGGER.warn(() -> {
                                return "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.";
                            });
                        }
                        definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
                        explicitFactoryUsed = true;
                    } else if (this.sqlSessionTemplate != null) {
                        if (explicitFactoryUsed) {
                            LOGGER.warn(() -> {
                                return "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.";
                            });
                        }
                        definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
                        explicitFactoryUsed = true;
                    }
             
                    if (!explicitFactoryUsed) {
                        LOGGER.debug(() -> {
                            return "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.";
                        });
                        definition.setAutowireMode(2);
                    }
                }
            }
        1. 從這個(gè)方法第一行開始debug,這里我使用@MapperScan("com.fast.framework.dao") 是掃描的com.fast.framework.dao包

        這個(gè)是掃描到的包,說明會掃描到子包,perfect,解決了開始提出的問題。

        總結(jié)

        其實(shí)這里的分析過程不是特別詳細(xì),因?yàn)榈竭@里是證明掃描出來的包,從而間接證明掃描到的包都會被使用。剩下的:上一步怎么掃描的全部包,還有掃描到包怎么初始化的都沒有詳細(xì)分析。所以也是小水一篇吧,主要是要明白@MapperScan注解會掃描包的子包和學(xué)會這種分析思路。

        來源:blog.csdn.net/Mint6/article/details/92441513

        覺得不錯(cuò),請點(diǎn)個(gè)在看

        瀏覽 162
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 夜夜爽网站 | 午夜国产精品福利 | 韩国免费毛片 | 宝贝奶水好甜h | 靠逼视频在线观看免费 |