亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

springboot默認掃描的路徑方式

 更新時間:2023年07月06日 14:44:21   作者:鶸者為何戰(zhàn)斗  
這篇文章主要介紹了springboot默認掃描的路徑方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

springboot默認掃描的路徑

一般來說spring boot默認的掃描路徑是啟動類當前的包和子包

@SpringBootApplication
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan(basePackages = {"com.frame.springboot.dao", "com.frame.springboot.base"})
public class SpringbootApplication {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(SpringbootApplication.class);
        app.addListeners(new MyApplicationStartedEventListener());
        app.run(args);
    }
    static class MyApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent> {
        private Logger logger = LoggerFactory.getLogger(MyApplicationStartedEventListener.class);
        @Override
        public void onApplicationEvent(ApplicationStartedEvent event) {
            SpringApplication app = event.getSpringApplication();
            app.setBannerMode(Banner.Mode.OFF);// 不顯示banner信息
            logger.info("==MyApplicationStartedEventListener==");
        }
    }
}

例如這個類的包和子類

接下來就從源碼角度來分析這是為什么

首先這個加載過程肯定是從refreshcontext中的操作,因此進入。

  public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);
            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }
                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }
        }
    }

這個操作實在初始化factorypostprocessors中進行的。

接下來進入方法

  protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

在這里很明顯是把任務委托給了PostProcessorRegistrationDelegate。

接下來我們繼續(xù)點擊進入

invokeBeanFactoryPostProcessors的方法很長我只截取我們關心的代碼

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        Set<String> processedBeans = new HashSet();
        int var9;
        ArrayList currentRegistryProcessors;
        String[] postProcessorNames;
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList();
            Iterator var6 = beanFactoryPostProcessors.iterator();
            while(var6.hasNext()) {
                BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }
}

這里先來簡單的說一下,首先會調(diào)用傳入的beanFactoryPostProcessors的postProcessBeanDefinitionRegistry。

處理一般會調(diào)用

ConfigurationClassPostProcessor類,接下來進去看一下postProcessBeanDefinitionRegistry方法

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        int registryId = System.identityHashCode(registry);
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        } else if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
        } else {
            this.registriesPostProcessed.add(registryId);
            this.processConfigBeanDefinitions(registry);
        }
    }

在這里最重要的還是processConfigBeanDefinitions方法,但是這個方法實在是太長了截取重要的步驟

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
          //省略
          parser.parse(candidates);
}

這個方法主要是用來解析beandefinitions。

進入看一下

   public void parse(Set<BeanDefinitionHolder> configCandidates) {
        this.deferredImportSelectors = new LinkedList();
        Iterator var2 = configCandidates.iterator();
        while(var2.hasNext()) {
            BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                if (bd instanceof AnnotatedBeanDefinition) {
                    this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
                } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
                    this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
                } else {
                    this.parse(bd.getBeanClassName(), holder.getBeanName());
                }
            } catch (BeanDefinitionStoreException var6) {
                throw var6;
            } catch (Throwable var7) {
                throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
            }
        }
        this.processDeferredImportSelectors();
    }

這由于我們使用的是注解來進行那么進入第一個parse,主要調(diào)用了processConfigurationClass 的方法

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
        if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            ConfigurationClass existingClass = (ConfigurationClass)this.configurationClasses.get(configClass);
            if (existingClass != null) {
                if (configClass.isImported()) {
                    if (existingClass.isImported()) {
                        existingClass.mergeImportedBy(configClass);
                    }
                    return;
                }
                this.configurationClasses.remove(configClass);
                Iterator it = this.knownSuperclasses.values().iterator();
                while(it.hasNext()) {
                    if (configClass.equals(it.next())) {
                        it.remove();
                    }
                }
            }
            ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass);
            do {
                sourceClass = this.doProcessConfigurationClass(configClass, sourceClass);
            } while(sourceClass != null);
            this.configurationClasses.put(configClass, configClass);
        }
    }

這個方法獲取config的class和解析,其中主要方法是doProcessConfigurationClass

    protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass) throws IOException {
     Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            Iterator var13 = componentScans.iterator();
            while(var13.hasNext()) {
                AnnotationAttributes componentScan = (AnnotationAttributes)var13.next();
                Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                Iterator var7 = scannedBeanDefinitions.iterator();
                while(var7.hasNext()) {
                    BeanDefinitionHolder holder = (BeanDefinitionHolder)var7.next();
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {
                        this.parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }
}

只截取了其中的重要部分,看到componentScanParser.parse了,那么基本就想到是要去獲取Component組件了,為什么config會和component關系呢,請看一下注解內(nèi)部里面有一個@component。

接下來進去看一下

    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
  Set<String> basePackages = new LinkedHashSet();
        String[] basePackagesArray = componentScan.getStringArray("basePackages");
        String[] var19 = basePackagesArray;
        int var21 = basePackagesArray.length;
        int var22;
        for(var22 = 0; var22 < var21; ++var22) {
            String pkg = var19[var22];
            String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ",; \t\n");
            basePackages.addAll(Arrays.asList(tokenized));
        }
        Class[] var20 = componentScan.getClassArray("basePackageClasses");
        var21 = var20.length;
        for(var22 = 0; var22 < var21; ++var22) {
            Class<?> clazz = var20[var22];
            basePackages.add(ClassUtils.getPackageName(clazz));
        }
        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }
}

這個代碼是為了尋找可以掃描的基礎包,但是在創(chuàng)建啟動類的時候我們并沒有設置也就是basePackages.isEmpty()==true。

接下來的操作是添加declaringClass路徑,那么這個類是什么呢。

這個類就是你的啟動類。

所以真正設置掃描路徑的代碼在這。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java線程同步機制_動力節(jié)點Java學院整理

    Java線程同步機制_動力節(jié)點Java學院整理

    在之前,已經(jīng)學習到了線程的創(chuàng)建和狀態(tài)控制,但是每個線程之間幾乎都沒有什么太大的聯(lián)系??墒怯械臅r候,可能存在多個線程多同一個數(shù)據(jù)進行操作,這樣,可能就會引用各種奇怪的問題。現(xiàn)在就來學習多線程對數(shù)據(jù)訪問的控制吧
    2017-05-05
  • java設計模式--橋接模式詳解

    java設計模式--橋接模式詳解

    這篇文章主要為大家詳細介紹了java設計模式之橋接模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助
    2021-07-07
  • 淺析Java中JNI靜態(tài)注冊和動態(tài)注冊

    淺析Java中JNI靜態(tài)注冊和動態(tài)注冊

    這篇文章主要為大家詳細介紹了Java中JNI靜態(tài)注冊和動態(tài)注冊的相關知識,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-12-12
  • 多模塊maven的deploy集成gitlab?ci自動發(fā)版配置

    多模塊maven的deploy集成gitlab?ci自動發(fā)版配置

    這篇文章主要為大家介紹了多模塊maven項目deploy集成gitlab?ci自動發(fā)版的配置流程步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-02-02
  • 微信小程序微信登錄的實現(xiàn)方法詳解(JAVA后臺)

    微信小程序微信登錄的實現(xiàn)方法詳解(JAVA后臺)

    通常我們在登錄微信小程序的時候都是通過授權(quán)登錄,下面這篇文章主要給大家介紹了關于微信小程序微信登錄的實現(xiàn)方法,文中通過實例代碼介紹的介紹的非常詳細,需要的朋友可以參考下
    2022-07-07
  • 淺談Java中對類的主動引用和被動引用

    淺談Java中對類的主動引用和被動引用

    這篇文章主要介紹了淺談Java中對類的主動引用和被動引用,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • Java使用PDFBox渲染生成pdf文檔的代碼詳解

    Java使用PDFBox渲染生成pdf文檔的代碼詳解

    使用PDFBox可以渲染生成pdf文檔,并且自定義程度高,只是比較麻煩,這篇文章將為大家詳細介紹一下具體的實現(xiàn)方法,感興趣的小伙伴可以參考一下
    2025-04-04
  • Java基礎學習之關鍵字和變量數(shù)據(jù)類型的那些事

    Java基礎學習之關鍵字和變量數(shù)據(jù)類型的那些事

    變量就是系統(tǒng)為程序分配的一塊內(nèi)存單元,用來存儲各種類型的數(shù)據(jù),下面這篇文章主要給大家介紹了關于Java基礎學習之關鍵字和變量數(shù)據(jù)類型的那些事,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-07-07
  • SpringBoot中的Javaconfig代碼示例

    SpringBoot中的Javaconfig代碼示例

    JavaConfig是一種使用Java類替代XML配置文件的方式來定義Spring?Bean的機制,通過使用`@Configuration`和`@Bean`注解,可以將第三方JAR包中的對象納入Spring?IOC容器管理,本文介紹SpringBoot中的Javaconfig,感興趣的朋友一起看看吧
    2025-02-02
  • Redis Spring配置集群過程

    Redis Spring配置集群過程

    這篇文章主要介紹了Redis Spring配置集群過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04

最新評論