最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot啟動(dòng)類和啟動(dòng)過(guò)程超詳細(xì)講解

 更新時(shí)間:2025年09月17日 09:14:08   作者:fixAllenSun  
springboot的啟動(dòng)經(jīng)過(guò)了一些一系列的處理,下面這篇文章主要介紹了Springboot啟動(dòng)類和啟動(dòng)過(guò)程的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

【一】Spring Boot 啟動(dòng)類的注解

Spring Boot 啟動(dòng)類通常就是一個(gè)標(biāo)注了 @SpringBootApplication的類,但這個(gè)注解是一個(gè)組合注解(Composite Annotation)?,理解它包含的元注解是關(guān)鍵。

【1】核心注解:@SpringBootApplication

這是啟動(dòng)類上唯一必須的注解,它整合了三個(gè)核心注解的功能:

(1)?@SpringBootConfiguration?:Spring容器會(huì)從該類中加載Bean定義

(1)?作用?:表明當(dāng)前類是一個(gè)配置類。它的底層是 @Configuration,這意味著Spring容器會(huì)從該類中加載Bean定義(@Bean注解的方法)。
(2)?為什么不用 @Configuration?:@SpringBootConfiguration是Spring Boot提供的,語(yǔ)義上更明確地指出這是主配置類,但在功能上與 @Configuration無(wú)異。

(2)?@EnableAutoConfiguration?:自動(dòng)配置依賴

(1)?作用?:?啟用Spring Boot的自動(dòng)配置機(jī)制。這是Spring Boot魔法(Convention over Configuration)的核心。
(2)?原理?:這個(gè)注解會(huì)通知Spring Boot根據(jù)你添加的jar包依賴(如classpath下是否存在DataSource、SpringMVC等類),自動(dòng)猜測(cè)并配置你需要的Bean。例如,當(dāng)你引入了spring-boot-starter-web,它會(huì)自動(dòng)配置Tomcat和Spring MVC。

(3)?@ComponentScan?:?自動(dòng)掃描并注冊(cè)Bean

(1)?作用?:?自動(dòng)掃描并注冊(cè)Bean。默認(rèn)會(huì)掃描啟動(dòng)類所在包及其所有子包下的所有組件,包括@Component, @Service, @Repository, @Controller等注解的類,并將它們注冊(cè)到Spring容器中。
(2)?重要提示?:這是為什么通常要把啟動(dòng)類放在項(xiàng)目根包(root package)下的原因。如果放在一個(gè)很深的包里,@ComponentScan可能無(wú)法掃描到其他重要的組件。

【2】其他常用注解(可根據(jù)需要添加)

雖然 @SpringBootApplication已經(jīng)足夠,但在某些場(chǎng)景下,你可能會(huì)在啟動(dòng)類上額外添加一些注解。

(1)?@EnableScheduling?

?作用?:?jiǎn)⒂肧pring的定時(shí)任務(wù)功能。添加后,可以使用 @Scheduled注解來(lái)創(chuàng)建定時(shí)任務(wù)。

(2)?@EnableAsync?

?作用?:?jiǎn)⒂肧pring的異步方法執(zhí)行功能。添加后,可以使用 @Async注解來(lái)標(biāo)記異步執(zhí)行的方法。

(3)?@EnableTransactionManagement?

?作用?:?jiǎn)⒂米⒔馐绞聞?wù)管理。不過(guò),當(dāng)Spring Boot檢測(cè)到存在事務(wù)管理器(如引入了JDBC或JPA starter)時(shí),此功能實(shí)際上是默認(rèn)開啟的。顯式添加此注解只是為了代碼意圖更清晰。

(4)?@EnableCaching?

?作用?:?jiǎn)⒂肧pring的注解驅(qū)動(dòng)緩存功能。添加后,可以使用 @Cacheable, @CacheEvict等注解。

(5)?@Import?

?作用?:用于導(dǎo)入其他配置類(通常是@Configuration類),這些配置類可能不在@ComponentScan的掃描路徑下。例如:@Import({CustomConfig.class, AnotherConfig.class})。

?總結(jié)?:對(duì)于大多數(shù)標(biāo)準(zhǔn)應(yīng)用,?只使用 @SpringBootApplication注解就足夠了。其他注解如 @EnableScheduling等,應(yīng)根據(jù)具體功能需求選擇性添加。

【3】@MapperScan

@MapperScan注解的主要目的是告訴 MyBatis 應(yīng)該去哪個(gè)或哪些包路徑下掃描 Mapper 接口,并自動(dòng)將其注冊(cè)為 Spring 容器中的 Bean(MapperFactoryBean)?。

(1)?解決了什么問題???

在沒有這個(gè)注解之前,你需要在每個(gè) Mapper 接口上手動(dòng)添加 @Mapper注解,或者手動(dòng)配置 MapperFactoryBean,非常繁瑣。@MapperScan通過(guò)包掃描的方式,實(shí)現(xiàn)了批量、自動(dòng)的注冊(cè),極大簡(jiǎn)化了配置。

(2)?底層機(jī)制:??

當(dāng) Spring 容器啟動(dòng)時(shí),它會(huì)處理 @MapperScan注解。MyBatis-Spring 整合模塊會(huì)為指定的包路徑創(chuàng)建 ClassPathMapperScanner,該掃描器會(huì)找到所有接口,并為每個(gè)接口動(dòng)態(tài)創(chuàng)建一個(gè) MapperFactoryBean的 BeanDefinition 注冊(cè)到 Spring 容器中。MapperFactoryBean是一個(gè) FactoryBean,它的 getObject()方法會(huì)使用 SqlSession為原始 Mapper 接口創(chuàng)建一個(gè)動(dòng)態(tài)代理實(shí)例,并將這個(gè)代理實(shí)例作為 Bean 交給 Spring 管理。這就是為什么你可以在 Service 層直接 @Autowired一個(gè)接口的原因。

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import @SpringBootApplication

// 方式一:直接掃描一個(gè)包
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

// 方式二:掃描多個(gè)包
@MapperScan(basePackages = {"com.example.mapper", "com.example.other.dao"})

// 方式三:類型安全的掃描(推薦)
// 創(chuàng)建一個(gè)空的標(biāo)記接口,放在 com.example.mapper 包下
public interface MapperScanMarker {
    // 無(wú)任何方法,僅作為包路徑標(biāo)記
}

@SpringBootApplication
// 掃描標(biāo)記接口所在的包
@MapperScan(basePackageClasses = MapperScanMarker.class)
public class DemoApplication {
    // ...
}

【4】自動(dòng)裝配原理

(1)自動(dòng)裝配的核心思想

?要解決的問題:?? 傳統(tǒng) Spring 應(yīng)用需要大量手動(dòng)配置(如 XML、Java Config)來(lái)集成第三方庫(kù)或框架(例如數(shù)據(jù)源、事務(wù)管理器、MVC 等)。這個(gè)過(guò)程繁瑣且容易出錯(cuò)。

?解決方案:?? Spring Boot 自動(dòng)裝配通過(guò)預(yù)先定義的條件,在檢測(cè)到項(xiàng)目的特定依賴、配置和類路徑后,自動(dòng)為應(yīng)用注入所需的 Bean 并完成配置。簡(jiǎn)單來(lái)說(shuō),就是 ??“如果我在類路徑上看到了 X,并且你沒有自己配置 Y,那么我就自動(dòng)給你配置一個(gè)默認(rèn)的 Y”?。

(2)實(shí)現(xiàn)原理的核心組件

(1)@SpringBootApplication與 @EnableAutoConfiguration

一切的起點(diǎn)是主啟動(dòng)類上的 @SpringBootApplication注解。它是一個(gè)組合注解?(Composite Annotation),其核心功能之一由 @EnableAutoConfiguration提供。

@SpringBootApplication // 這是一個(gè)元注解,整合了其他注解的功能
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

@EnableAutoConfiguration本身又是一個(gè)開關(guān)注解,它通過(guò) @Import導(dǎo)入了最核心的加載器:AutoConfigurationImportSelector。

(2)AutoConfigurationImportSelector

這個(gè)類是自動(dòng)裝配的大腦。它的核心任務(wù)是決定需要導(dǎo)入哪些自動(dòng)配置類。

?工作原理?:AutoConfigurationImportSelector會(huì)讀取項(xiàng)目 classpath 下所有 JAR 包中的 ?META-INF/spring.factories? 文件。

?關(guān)鍵文件?:在 spring-boot-autoconfigure-x.x.x.x.jar中,META-INF/spring.factories文件是一個(gè)鍵值對(duì)形式的配置文件。其中 EnableAutoConfiguration這個(gè) key 后面列出了一長(zhǎng)串的自動(dòng)配置類(XXXAutoConfiguration)。

?spring.factories文件片段示例:??

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
# ... 省略上百個(gè)配置類
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

AutoConfigurationImportSelector會(huì)獲取所有這些配置類的全限定名,并將它們作為候選配置類。

(3)@Conditional條件注解家族 - ?靈魂所在?

僅僅將候選配置類全部加載是不行的,Spring Boot 需要根據(jù)當(dāng)前應(yīng)用的環(huán)境來(lái)智能判斷哪些配置類應(yīng)該真正生效。這就是 @Conditional系列注解的作用。

這些注解是自動(dòng)裝配的“開關(guān)”,它們會(huì)在配置類或 Bean 被加載前進(jìn)行條件判斷,只有滿足所有條件,配置才會(huì)生效。

(4)XXXAutoConfiguration自動(dòng)配置類

這些是具體的執(zhí)行者。每個(gè) XXXAutoConfiguration都是一個(gè)標(biāo)準(zhǔn)的 ?Spring 配置類?(@Configuration),其內(nèi)部使用 @Bean方法來(lái)定義組件,并且方法上通常裝飾著各種 @Conditional注解。

【二】Spring Boot 項(xiàng)目啟動(dòng)的詳細(xì)流程

Spring Boot 的啟動(dòng)流程可以看作是傳統(tǒng) Spring 應(yīng)用啟動(dòng)流程的一個(gè)高度封裝和自動(dòng)化版本。其核心是 SpringApplication.run(Application.class, args)方法。

以下是其詳細(xì)步驟:

【1】?啟動(dòng) Main 方法?

JVM 調(diào)用應(yīng)用程序的 main方法。

【2】?創(chuàng)建 SpringApplication 實(shí)例?:

(1)在 run方法內(nèi)部,首先會(huì)創(chuàng)建一個(gè) SpringApplication實(shí)例。

(2)這個(gè)實(shí)例會(huì)進(jìn)行一些初始化工作,例如:

1-?推斷應(yīng)用類型?:判斷是普通的Servlet應(yīng)用(Spring MVC)還是響應(yīng)式Web應(yīng)用(WebFlux)。

?2-初始化器(Initializers)??:加載 META-INF/spring.factories文件中配置的 ApplicationContextInitializer。

?3-監(jiān)聽器(Listeners)??:加載 META-INF/spring.factories文件中配置的 ApplicationListener(應(yīng)用監(jiān)聽器)。這些監(jiān)聽器將用于接收整個(gè)啟動(dòng)過(guò)程中發(fā)布的各種事件。

【3】?運(yùn)行 SpringApplication 實(shí)例(run方法)??:這是最復(fù)雜的核心階段。

(1)?a. 啟動(dòng)計(jì)時(shí)器 & 發(fā)布開始事件?:?jiǎn)?dòng)一個(gè)計(jì)時(shí)器,并發(fā)布 ApplicationStartingEvent事件。此時(shí)容器還未創(chuàng)建,任何Bean都未初始化。

(2)?b. 準(zhǔn)備環(huán)境(Environment)??:創(chuàng)建并配置應(yīng)用運(yùn)行環(huán)境(Environment),讀取所有配置源(application.properties/yaml、系統(tǒng)屬性、環(huán)境變量等)。發(fā)布 ApplicationEnvironmentPreparedEvent事件。

(3)?c. 創(chuàng)建應(yīng)用上下文(ApplicationContext)??:根據(jù)第一步推斷的應(yīng)用類型,創(chuàng)建對(duì)應(yīng)的 ApplicationContext(例如,對(duì)于Servlet應(yīng)用,創(chuàng)建 AnnotationConfigServletWebServerApplicationContext)。

(4)?d. 準(zhǔn)備應(yīng)用上下文?:

  • 將環(huán)境(Environment)設(shè)置到上下文中。
  • 執(zhí)行所有 ApplicationContextInitializer的 initialize方法,對(duì)上下文進(jìn)行自定義初始化。
  • 發(fā)布 ApplicationContextInitializedEvent事件。

(5)?e. 刷新應(yīng)用上下文(核心中的核心)??:調(diào)用上下文的 refresh()方法。這一步完成了傳統(tǒng)Spring應(yīng)用容器的所有初始化工作:

  • ?加載Bean定義?:解析啟動(dòng)類(因?yàn)樗茾Configuration),執(zhí)行@ComponentScan掃描并注冊(cè)所有Bean定義。
  • ?執(zhí)行自動(dòng)配置?:執(zhí)行 @EnableAutoConfiguration邏輯,加載 spring-boot-autoconfigurejar 包中 META-INF/spring.factories文件里的所有自動(dòng)配置類(XXXAutoConfiguration),根據(jù)條件(@ConditionalOnXxx)判斷是否需要配置相應(yīng)的Bean。
  • ?初始化Bean?:實(shí)例化所有非懶加載的單例Bean。

(6)?f. 后置處理?:執(zhí)行 CommandLineRunner和 ApplicationRunner接口的實(shí)現(xiàn)Bean。

(7)?g. 啟動(dòng)完成?:發(fā)布 ApplicationStartedEvent事件,啟動(dòng)計(jì)時(shí)器停止,打印啟動(dòng)耗時(shí)日志。

整個(gè)流程伴隨著事件的發(fā)布,允許開發(fā)者通過(guò)監(jiān)聽這些事件在特定階段插入自定義邏輯。

【三】Spring Boot 生命周期中的擴(kuò)展點(diǎn)及使用案例

Spring Boot 在整個(gè)生命周期中提供了大量“鉤子”(Hook),允許開發(fā)者介入并執(zhí)行自定義邏輯。以下是一些最重要的擴(kuò)展點(diǎn):

【1】Application Events(應(yīng)用事件) - 觀察者模式

通過(guò)實(shí)現(xiàn) ApplicationListener接口或使用 @EventListener注解來(lái)監(jiān)聽特定事件。

?常用事件?:

  • ApplicationStartingEvent:應(yīng)用剛啟動(dòng),任何處理都還未進(jìn)行。
  • ApplicationEnvironmentPreparedEvent:環(huán)境已準(zhǔn)備完畢,上下文還未創(chuàng)建。
  • ApplicationContextInitializedEvent:上下文已創(chuàng)建且初始化器已被調(diào)用,但Bean定義還未加載。
  • ApplicationPreparedEvent:Bean定義已加載,但Bean還未實(shí)例化。
  • ApplicationStartedEvent:上下文已刷新,所有Bean已實(shí)例化,CommandLineRunner/ApplicationRunner還未執(zhí)行。
  • ApplicationReadyEvent:應(yīng)用已完全啟動(dòng),可以正常接收請(qǐng)求。

案例:在應(yīng)用啟動(dòng)成功后打印一條日志?java

import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class StartupNotifier {

    @EventListener(ApplicationReadyEvent.class)
    public void onAppReady() {
        System.out.println("?? Application is now ready and can serve traffic!");
        // 可以在這里執(zhí)行一些啟動(dòng)后的檢查,比如檢查數(shù)據(jù)庫(kù)連接狀態(tài)等
    }
}

【2】ApplicationContextInitializer(應(yīng)用上下文初始化器)

在 ApplicationContext刷新(refresh)之前,對(duì)其執(zhí)行自定義的初始化操作。

?案例:在上下文準(zhǔn)備階段設(shè)置一個(gè)自定義屬性?java

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

public class MyInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // 向環(huán)境中添加一個(gè)屬性
        applicationContext.getEnvironment().getSystemProperties().put("myCustomProperty", "initialized");
    }
}

?注冊(cè)方式?:需要在 META-INF/spring.factories文件中注冊(cè)。

復(fù)制org.springframework.context.ApplicationContextInitializer=com.example.MyInitializer

【3】CommandLineRunner / ApplicationRunner

在應(yīng)用上下文刷新完成后、應(yīng)用完全啟動(dòng)之前,執(zhí)行一些特定的代碼。非常適合進(jìn)行數(shù)據(jù)初始化、緩存預(yù)熱等操作。兩者功能幾乎一樣,區(qū)別在于參數(shù):

  • CommandLineRunner:提供原始的字符串?dāng)?shù)組參數(shù) String… args(即main方法的args)。
  • ApplicationRunner:提供更結(jié)構(gòu)化的 ApplicationArguments對(duì)象來(lái)解析參數(shù)。

?案例:應(yīng)用啟動(dòng)后初始化一些數(shù)據(jù)?java

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class DataLoader implements CommandLineRunner {

    private final UserRepository userRepository;

    public DataLoader(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void run(String... args) throws Exception {
        // 檢查數(shù)據(jù)庫(kù)是否已有數(shù)據(jù),如果沒有則插入默認(rèn)數(shù)據(jù)
        if (userRepository.count() == 0) {
            User admin = new User("admin", "admin@example.com");
            userRepository.save(admin);
            System.out.println("Initial admin user created.");
        }
    }
}

【4】Spring Bean 生命周期鉤子

這是 Spring 框架本身的擴(kuò)展點(diǎn),在 Spring Boot 中同樣適用。

  • @PostConstruct:在Bean的依賴注入完成后,初始化方法(InitializingBean.afterPropertiesSet)之前執(zhí)行。
  • InitializingBean接口:實(shí)現(xiàn) afterPropertiesSet()方法,在所有屬性設(shè)置完成后執(zhí)行。
  • @PreDestroy:在Bean被容器銷毀之前執(zhí)行。

?案例:Bean初始化后連接資源?java

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class ResourceConnector {

    @PostConstruct
    public void connect() {
        System.out.println("Connecting to external resource...");
        // 初始化連接
    }

    @PreDestroy
    public void disconnect() {
        System.out.println("Disconnecting from external resource...");
        // 關(guān)閉連接,釋放資源
    }
}

【四】Spring Bean 生命周期中的重要組件

【1】BeanPostProcessor (BPP) - 容器級(jí)后處理器?

(1)?作用?:這是Spring框架最強(qiáng)大、最核心的擴(kuò)展接口。它作用于整個(gè)ApplicationContext,對(duì)所有Bean的初始化過(guò)程進(jìn)行攔截和增強(qiáng)。你可以把它想象成一個(gè)“Bean加工流水線”。

(2)?兩個(gè)核心方法?:

  • 1-postProcessBeforeInitialization(Object bean, String beanName):在Bean的初始化回調(diào)方法?(如@PostConstruct)之前執(zhí)行??梢詫?duì)Bean進(jìn)行包裝或替換(例如返回一個(gè)代理對(duì)象,AOP就是基于此實(shí)現(xiàn)的)。
  • 2-postProcessAfterInitialization(Object bean, String beanName):在Bean的初始化回調(diào)方法之后執(zhí)行。此時(shí)Bean已基本完成初始化。

(3)?重要實(shí)現(xiàn)?:AutowiredAnnotationBeanPostProcessor(處理@Autowired注解)、CommonAnnotationBeanPostProcessor(處理@PostConstruct、@Resource等)、AnnotationAwareAspectJAutoProxyCreator(負(fù)責(zé)AOP動(dòng)態(tài)代理)。

【2】BeanFactoryPostProcessor (BFPP) - 工廠級(jí)后處理器?

(1)?作用?:在Bean實(shí)例化之前,可以讀取、修改Bean的定義(BeanDefinition)。它操作的是“藍(lán)圖”,而不是Bean實(shí)例本身。

(2)?核心方法?:postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

(3)?經(jīng)典案例?:PropertySourcesPlaceholderConfigurer(處理 ${…}占位符)就是在此時(shí)將Bean定義中的占位符替換為實(shí)際的屬性值。

【3】Aware 接口族 - 感知接口?

?(1)作用?:讓Bean能“感知”到容器本身和某些特定的資源。這些接口的回調(diào)發(fā)生在BeanPostProcessor之前,初始化方法之后。

(2)?常用接口?:

  • 1-BeanNameAware:感知自己在容器中的Bean名稱。
  • 2-ApplicationContextAware:感知自己所在的ApplicationContext(這是手動(dòng)獲取Bean的一種方式)。
  • 3-BeanFactoryAware:感知?jiǎng)?chuàng)建自己的BeanFactory。

【4】生命周期回調(diào)注解/接口?

(1)?作用?:定義Bean自身初始化和銷毀時(shí)的行為。

(2)?初始化?:

  • ?JSR-250注解?:@PostConstruct(推薦使用,標(biāo)準(zhǔn)注解)。
  • ?Spring接口?:InitializingBean及其 afterPropertiesSet()方法。
  • ?XML配置?:init-method屬性。

(3)?銷毀?:

  • ?JSR-250注解?:@PreDestroy(推薦使用)。
  • ?Spring接口?:DisposableBean及其 destroy()方法。
  • ?XML配置?:destroy-method屬性。

【5】生命周期執(zhí)行順序

?執(zhí)行順序?:BeanFactoryPostProcessor-> BeanPostProcessor的Before-> Aware接口 -> @PostConstruct-> InitializingBean-> init-method-> BeanPostProcessor的After-> … -> @PreDestroy-> DisposableBean-> destroy-method。

總結(jié)

到此這篇關(guān)于Springboot啟動(dòng)類和啟動(dòng)過(guò)程的文章就介紹到這了,更多相關(guān)Springboot啟動(dòng)類和啟動(dòng)過(guò)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

伊金霍洛旗| 兴隆县| 邓州市| 腾冲县| 自贡市| 太康县| 长海县| 黄大仙区| 商南县| 调兵山市| 新竹市| 广南县| 江陵县| 浙江省| 三都| 城口县| 丹东市| 泾川县| 黔江区| 普陀区| 台北市| 枞阳县| 黄大仙区| 通城县| 霍城县| 岳阳县| 奎屯市| 蒲城县| 获嘉县| 丹阳市| 远安县| 黎平县| 苗栗市| 嘉禾县| 且末县| 柏乡县| 大连市| 公主岭市| 黄龙县| 民勤县| 紫云|