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

Spring?Bean作用域、生命周期與自動裝配深入解析

 更新時間:2025年12月24日 15:19:07   作者:九轉(zhuǎn)蒼翎  
本文詳細介紹了SpringBoot中Bean的作用域、生命周期以及自動裝配的概念,Bean的作用域包括Singleton、Prototype、Request、Session和Application,文章還解析了SpringBoot的自動配置機制和Gitee上的相關(guān)資源,感興趣的朋友跟隨小編一起看看吧

SpringBoot版本:3.5.8

1.Bean的作用域

Spring Bean的作用域定義了Bean的作用范圍,即Bean在哪些上下文中可用

/**
 * 實體類
 */
public class Dog {
}
/**
 * 配置類
 */
@Configuration
public class DogConfig {
    //單例
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    public Dog singleDog(){
        return new Dog();
    }
    //原型
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Dog prototypeDog(){
        return new Dog();
    }
    //請求
    @Bean
    @RequestScope
    public Dog requestDog(){
        return new Dog();
    }
    //會話
    @Bean
    @SessionScope
    public Dog sessionDog(){
        return new Dog();
    }
    //應(yīng)用
    @Bean
    @ApplicationScope
    public Dog applicationDog(){
        return new Dog();
    }
}
/**
 * 啟動類
 */
@SpringBootApplication
public class SpringPrincipleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringPrincipleApplication.class, args);
    }
}
/**
 * 視圖層
 */
@RequestMapping("/test")
@RestController
public class TestController {
    private final Dog single;
    private final Dog prototype;
    private final Dog request;
    private final Dog session;
    private final Dog application;
    private final ApplicationContext context;
    public TestController(@Qualifier("singleDog") Dog single, @Qualifier("prototypeDog") Dog prototype,
                          @Qualifier("requestDog") Dog request, @Qualifier("sessionDog") Dog session,
                          @Qualifier("applicationDog") Dog application, ApplicationContext context) {
        this.single = single;
        this.prototype = prototype;
        this.request = request;
        this.session = session;
        this.application = application;
        this.context = context;
    }
    @RequestMapping("/single")
    public String single(){
        Dog singleDog = (Dog)context.getBean("singleDog");
        return "dog: " + this.single.toString() + "
" + "contextDog: " + singleDog;
    }
    @RequestMapping("/prototype")
    public String prototype(){
        Dog prototypeDog = (Dog)context.getBean("prototypeDog");
        return "dog: " + this.prototype.toString() + "
" + "contextDog: " + prototypeDog;
    }
    @RequestMapping("/request")
    public String request(){
        Dog requestDog = (Dog)context.getBean("requestDog");
        return "dog: " + this.request.toString() + "
" + "contextDog: " + requestDog;
    }
    @RequestMapping("/session")
    public String session(){
        Dog sessionDog = (Dog)context.getBean("sessionDog");
        return "dog: " + this.session.toString() + "
" + "contextDog: " + sessionDog;
    }
    @RequestMapping("/application")
    public String application(){
        Dog applicationDog = (Dog)context.getBean("applicationDog");
        return "dog: " + this.application.toString() + "
" + "contextDog: " + applicationDog;
    }
}

Singleton(單例):默認作用域,每個Spring容器中僅存在一個Bean實例

Prototype(原型):每次請求Bean時都會創(chuàng)建一個新的實例

  • 直接通過context.getBean()獲取會觸發(fā)新實例創(chuàng)建
  • 當(dāng)使用@Autowired@Resource注入prototype作用域的Bean時:注入操作僅在初始化階段(Spring容器創(chuàng)建和配置Bean的過程)執(zhí)行一次,后續(xù)通過字段引用訪問的是最初注入的實例,不會因后續(xù)請求自動重新注入新實例
  • Request(請求):每個HTTP請求創(chuàng)建一個新的Bean實例,僅在Web應(yīng)用中有效

  • 1.代理注入:當(dāng)使用@Autowired注入Request作用域的Bean時,Spring實際上注入的是一個代理對象而非真實實例。代理對象在應(yīng)用啟動時就被注入到依賴它的單例Bean中,但真實實例的創(chuàng)建被延遲到HTTP請求發(fā)生時
  • 2.方法調(diào)用:注入的代理對象內(nèi)部持有對當(dāng)前HTTP請求上下文的引用。當(dāng)調(diào)用代理對象的方法時,代理會從當(dāng)前請求的上下文中查找或創(chuàng)建新的真實實例
  • 3.實例操作:雖然依賴注入發(fā)生在容器初始化階段,但通過代理模式將實例的獲取延遲到實際方法調(diào)用時,這種延遲查找機制確保每個請求線程都能獲得獨立的實例
  • Session(會話):每個用戶會話創(chuàng)建一個Bean實例,僅在Web應(yīng)用中有效

Application(應(yīng)用):整個Web應(yīng)用共享一個Bean實例

2. Bean的生命周期

生命周期指的是一個對象從創(chuàng)建到銷毀的整個生命過程。Bean的生命周期分為以下5個部分:

  • 實例化:容器通過反射調(diào)用Bean的構(gòu)造器創(chuàng)建對象實例
  • 屬性賦值:容器注入依賴的屬性值(例如@Autowired)
  • 初始化:
    • 通知方法調(diào)用:通過特定接口(如Spring的BeanNameAware)注入框架相關(guān)依賴或上下文信息
    • 前置處理:進行準備工作,例如參數(shù)校驗、資源加載或權(quán)限檢查。確保主邏輯具備執(zhí)行條件,避免運行時錯誤
    • 初始化回調(diào):在對象初始化階段觸發(fā)的自定義邏輯(如實現(xiàn)InitializingBean接口的afterPropertiesSet方法)。用于完成屬性設(shè)置后的額外初始化操作
    • 后置處理:在流程結(jié)束后執(zhí)行清理或結(jié)果處理(如AOP中的@After通知)
  • 使用Bean:Bean進入就緒狀態(tài),可被應(yīng)用程序調(diào)用
  • 銷毀Bean:容器關(guān)閉時觸發(fā)銷毀

2.1 示例

/**
 * 實體類
 */
public class Cat {
}
/**
 * 配置類
 */
@Configuration
public class CatConfig {
    @Bean
    public Cat cat(){
        return new Cat();
    }
}
/**
 * 實現(xiàn)類
 */
@Component
@Slf4j
public class BeanLifeComponent implements BeanNameAware, BeanPostProcessor, InitializingBean {
    private Cat cat;
    //1.實例化:執(zhí)行構(gòu)造方法
    public BeanLifeComponent() {
        log.info("1.實例化:執(zhí)行構(gòu)造方法");
    }
    //2.屬性賦值:執(zhí)行setter方法
    @Autowired
    public void setCat(Cat cat) {
        log.info("2.屬性賦值:執(zhí)行setter方法");
        this.cat = cat;
    }
    //3.1 通知方法調(diào)用
    @Override
    public void setBeanName(String name) {
        log.info("3.1 通知方法調(diào)用,bean name is {}", name);
    }
    //3.2 前置處理
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("3.3 前置處理,bean:{},beanName:{}", bean, beanName);
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }
    //3.3初始化回調(diào)
    @Override
    public void afterPropertiesSet() {
        log.info("3.2初始化回調(diào)");
    }
    //3.4后置處理
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("3.4后置處理,bean:{},beanName:{}", bean, beanName);
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
    //4.使用Bean
    public void use(){
        log.info("4.使用Bean");
    }
    //5.銷毀Bean
    @PreDestroy
    public void preDestroy(){
        log.info("5.銷毀Bean");
    }
}
/**
 * 測試類
 */
@SpringBootTest
class SpringPrincipleApplicationTests {
    private final ApplicationContext context;
    @Autowired
    public SpringPrincipleApplicationTests(ApplicationContext context) {
        this.context = context;
    }
    @Test
    public void test(){
        BeanLifeComponent beanLifeComponent = context.getBean(BeanLifeComponent.class);
        beanLifeComponent.use();
    }
}

日志顯示的順序是:

  • invokeInitMethods(初始化回調(diào))
  • applyBeanPostProcessorsBeforeInitialization(前置處理)
  • applyBeanPostProcessorsAfterInitialization(后置處理)

這看起來與我上述介紹的生命周期流程相矛盾,具體解釋放在源碼解析后

2.2 源碼解析

AbstractAutowireCapableBeanFactory 類的作用:主要負責(zé)Bean的創(chuàng)建、依賴注入以及初始化等生命周期管理
(該思維導(dǎo)圖中的圖片看不清楚,原圖放在下述流程中)

  • 1.搜索AbstractAutowireCapableBeanFactory 類,并找到它的createBean方法
  • 2.createBean方法中調(diào)用了doCreateBean方法

  • 3.doCreateBean方法中依次調(diào)用了createBeanInstance、populateBeaninitializeBean方法

3.1

3.2

3.3 初始化:initializeBean方法中依次調(diào)用了invokeAwareMethodsapplyBeanPostProcessorsBeforeInitialization、invokeInitMethodsapplyBeanPostProcessorsAfterInitialization方法

3.3.1

3.3.2

3.3.3

3.3.4

2.3 日志與源碼“沖突”的原因分析

根據(jù)源碼來看,正確的生命周期流程是:前置處理 → 初始化回調(diào) → 后置處理。與上述我運行輸出的日志相矛盾

關(guān)鍵點:BeanPostProcessor本身也是Bean,當(dāng)Spring初始化一個BeanPostProcessor實現(xiàn)類(BeanLifeComponent類)時,這個過程是遞歸的

執(zhí)行流程分析:

  • 1.創(chuàng)建非BeanPostProcessor Bean(BeanLifeComponent類):
    • 按照源碼順序正常執(zhí)行:BeforeInitialization → InitMethods → AfterInitialization
  • 2.創(chuàng)建BeanPostProcessor Bean時:
    • Spring需要先讓這個BeanPostProcessor對象本身完成初始化(調(diào)用invokeInitMethods)
    • 然后才能將它加入到BeanPostProcessor列表中,供后續(xù)其他Bean(BeanLifeComponent類)使用
    • 但對于這個BeanPostProcessor Bean自己來說:
    • 它自己的afterPropertiesSet方法會在invokeInitMethods中執(zhí)行(初始化回調(diào)階段)
      • 但它自己的postProcessBeforeInitialization(前置處理)/postProcessAfterInitialization(后置)方法不會在它自己的創(chuàng)建過程中被調(diào)用!

上述日志中的情況解釋:日志顯示的是 一個BeanPostProcessor實現(xiàn)類(BeanLifeComponent類)的初始化過程:

  • 3.2 初始化回調(diào) - 這個BeanPostProcessor Bean自己的afterPropertiesSet()
  • 3.3 前置處理 - BeanLifeComponent類對這個BeanPostProcessor Bean的處理
  • 3.4 后置處理 - BeanLifeComponent類對這個BeanPostProcessor Bean的處理

3.SpringBoot自動裝配

作用:自動注冊Bean到Spring容器,不需要手動配置,通過約定大于配置的方式減少手動配置的復(fù)雜性。換言之,SpringBoo的自動配置就是將依賴Jar包中的配置類以及Bean加載到Ioc容器的過程

3.1 SpringBoot加載Bean

在pom.xml文件中引入第三方依賴,實際上就是將第三方代碼引入到SpringBoot項目中。SpringBoot項目在啟動時能識別這些依賴并自動將它們的配置類以及Bean加載到Ioc容器的過程。下面,我將編寫代碼作為第三方依賴,深入解析SpringBoot加載Bean的原理

創(chuàng)建目錄

編寫代碼

/**
 * 配置類
 */
@Slf4j
@Component
public class TestConfig {
    public void demo(){
        log.info("demo");
    }
}
/**
 * 測試類
 */
@SpringBootTest
public class SpringPrincipleApplicationTests {
    private final ApplicationContext context;
    @Autowired
    public SpringPrincipleApplicationTests(ApplicationContext context) {
        this.context = context;
    }
    @Test
    public void demo(){
        TestConfig testConfig = context.getBean(TestConfig.class);
        testConfig.demo();
    }
}

運行項目

  • 錯誤日志解析:在Java外功精要(2)——Spring IoC&DI一文中有詳細介紹。Spring通過五大注解 + @Bean可以將Bean加載到Ioc容器中,前提是這些注解類需要保證和SpringBoot啟動類(@SpringBootApplication)在同一目錄或者其子目錄下

下面介紹幾種解決方法

3.1.1 @ComponentScan

作用:告訴Spring容器去哪里掃描那些被@Component、@Service、@Repository、@Controller等注解標記的類,并將它們自動注冊為Bean

@SpringBootApplication
@ComponentScan("com.example.springprincicle.component")
public class SpringPrincipleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringPrincipleApplication.class, args);
    }
}

3.1.2 @Import

作用:用于將一個或多個配置類、組件類或其他類導(dǎo)入到當(dāng)前的Spring應(yīng)用上下文中

用法一:導(dǎo)入單個類

@SpringBootApplication
@Import(TestConfig.class)
public class SpringPrincipleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringPrincipleApplication.class, args);
    }
}

用法二:ImportSelector接口實現(xiàn)類

@Slf4j
@Component
public class DemoConfig {
    public void demo(){
        log.info("demo");
    }
}
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.example.springprincicle.component.TestConfig",
                "com.example.springprincicle.component.DemoConfig"};
    }
}
@SpringBootTest
public class SpringPrincipleApplicationTests {
    private final ApplicationContext context;
    @Autowired
    public SpringPrincipleApplicationTests(ApplicationContext context) {
        this.context = context;
    }
    @Test
    public void demo(){
        TestConfig testConfig = context.getBean(TestConfig.class);
        testConfig.demo();
        DemoConfig demoConfig = context.getBean(DemoConfig.class);
        demoConfig.demo();
    }
}

3.1.3 自定義注解

在使用@Import注解導(dǎo)入Bean時,需要程序員熟悉第三方依賴的所有配置類、組件類或其他類,這對于程序員開發(fā)程序十分不友好。所以,應(yīng)該由依賴的開發(fā)者來做這件事

比較常見的方案就是第三方依賴給我們提供一個注解,該注解內(nèi)部封裝@Import注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)
public @interface EnableTestConfig {
}
@SpringBootApplication
@EnableTestConfig
public class SpringPrincipleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringPrincipleApplication.class, args);
    }
}

3.2 @SpringBootApplication源碼解析

@SpringBootApplication是一個組合注解,包含以下三個核心注解的功能

3.2.1 @ComponentScan

  • 排除不需要掃描的配置類,防止自動配置類被重復(fù)掃描或注冊
  • @SpringBootApplication注解中,@ComponentScan注解沒有指定掃描路徑,那么默認掃描路徑為 @SpringBootApplication標注的類的類路徑

3.2.2 @SpringBootConfiguration

  • 標記該類為Spring的配置類
  • @Indexed:為Spring的組件掃描提供索引支持,加速應(yīng)用啟動時的類加載過程

3.2.3 @EnableAutoConfiguration

AutoConfigurationImportSelector類:它實現(xiàn)了 DeferredImportSelector 接口,負責(zé)在Spring 應(yīng)用啟動時動態(tài)加載自動配置類

    //JDK源碼,AutoConfigurationImportSelector類
    @Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}
  • getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes):在Spring Boot 3.5.8(本文所用的版本)中,該方法不僅加載 Spring Boot 默認的自動配置類,還會加載所有第三方庫提供的自動配置類
	//JDK源碼,AutoConfigurationImportSelector類
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		ImportCandidates importCandidates = ImportCandidates.load(this.autoConfigurationAnnotation,
				getBeanClassLoader());//掃描類路徑下的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
		List<String> configurations = importCandidates.getCandidates();//從 ImportCandidates 對象中獲取所有找到的自動配置類名,這些類名是從 .imports 文件中讀取的
		Assert.state(!CollectionUtils.isEmpty(configurations),
				"No auto configuration classes found in " + "META-INF/spring/"
						+ this.autoConfigurationAnnotation.getName() + ".imports. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}
  • 遵循 Spring Boot 的"約定優(yōu)于配置"理念,第三方依賴庫需要將其自動配置類定義在 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中,這樣 Spring Boot 啟動時就能自動發(fā)現(xiàn)并加載這些配置

fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions):體現(xiàn)了Spring Framework/Spring Boot的向后兼容性設(shè)計。即使在 Spring Boot 3.x 中引入了新的 .imports 機制,Spring Framework 仍然保留了 spring.factories 的支持

    //JDK源碼,AutoConfigurationImportSelector類
    private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
		List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
		if (!listeners.isEmpty()) {
			AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
			for (AutoConfigurationImportListener listener : listeners) {
				invokeAwareMethods(listener);
				listener.onAutoConfigurationImportEvent(event);
			}
		}
	}
	protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
		return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
	}
	public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
		return forDefaultResourceLocation(classLoader).load(factoryType);
	}
	public static SpringFactoriesLoader forDefaultResourceLocation(@Nullable ClassLoader classLoader) {
		return forResourceLocation(FACTORIES_RESOURCE_LOCATION, classLoader);
	}
	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

4.Gitee

Gitee地址:九轉(zhuǎn)蒼翎
本文源碼:spring-principle

到此這篇關(guān)于拆解Spring Bean作用域、生命周期與自動裝配的文章就介紹到這了,更多相關(guān)Spring Bean作用域、生命周期與自動裝配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解析Spring RestTemplate必須搭配MultiValueMap的理由

    解析Spring RestTemplate必須搭配MultiValueMap的理由

    本文給大家介紹Spring RestTemplate必須搭配MultiValueMap的理由,本文通過實例圖文相結(jié)合給大家介紹的非常詳細,需要的朋友參考下吧
    2021-11-11
  • SpringBoot項目集成Swagger和swagger-bootstrap-ui及常用注解解讀

    SpringBoot項目集成Swagger和swagger-bootstrap-ui及常用注解解讀

    這篇文章主要介紹了SpringBoot項目集成Swagger和swagger-bootstrap-ui及常用注解解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java模擬微信來電提醒示例

    Java模擬微信來電提醒示例

    這篇文章主要為大家介紹了Java模擬微信來電提醒示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • javaWeb自定義標簽用法實例詳解

    javaWeb自定義標簽用法實例詳解

    這篇文章主要介紹了javaWeb自定義標簽用法,結(jié)合實例形式分析了javaweb自定義標簽的功能、定義方法及執(zhí)行原理,需要的朋友可以參考下
    2017-04-04
  • Spring項目中如何自定義序列化工具

    Spring項目中如何自定義序列化工具

    這篇文章主要為大家詳細介紹了Spring項目中自定義序列化工具的相關(guān)知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • SpringBoot集成mqtt的多模塊項目配置詳解

    SpringBoot集成mqtt的多模塊項目配置詳解

    這篇文章主要介紹了SpringBoot集成mqtt的多模塊項目配置詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Spring的BeanUtils.copyProperties屬性復(fù)制避坑指南

    Spring的BeanUtils.copyProperties屬性復(fù)制避坑指南

    這篇文章主要介紹了Spring的BeanUtils.copyProperties屬性復(fù)制避坑指南,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 關(guān)于springboot的跨域配置問題的解決方案

    關(guān)于springboot的跨域配置問題的解決方案

    這篇文章主要介紹了關(guān)于springboot的跨域配置問題,處理filter,spring?security等過濾器跨域問題,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Java并發(fā)框架:Executor API詳解

    Java并發(fā)框架:Executor API詳解

    這篇文章主要介紹了Java并發(fā)框架:Executor API詳解,隨著當(dāng)今處理器中可用的核心數(shù)量的增加, 隨著對實現(xiàn)更高吞吐量的需求的不斷增長,多線程 API 變得非常流行。 Java 提供了自己的多線程框架,稱為 Executor 框架,需要的朋友可以參考下
    2019-07-07
  • MyBatis-Plus如何實現(xiàn)自動加密解密

    MyBatis-Plus如何實現(xiàn)自動加密解密

    這篇文章主要介紹了MyBatis-Plus實現(xiàn)自動加密解密方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評論

定安县| 丘北县| 黑龙江省| 铜川市| 阿荣旗| 武平县| 永丰县| 峨眉山市| 昌图县| 宁德市| 霞浦县| 临海市| 大方县| 民丰县| 盘山县| 贺兰县| 成安县| 韩城市| 塔城市| 耿马| 精河县| 凉山| 台北县| 乐东| 剑阁县| 堆龙德庆县| 阜新| 遂昌县| 延川县| 扬中市| 苏尼特右旗| 兴安盟| 东源县| 浦县| 阳春市| 清苑县| 宁蒗| 龙岩市| 九台市| 三亚市| 吴旗县|