springboot 读取application.properties流程

9 篇文章 0 订阅
订阅专栏

一、application.properties配置如下,当然也可以配置YAML。

application-dev.properties

server.port=8110
spring.application.name=newday-service


spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

logging.level.org.hibernate.type.descriptor.sql.BasicBinder=trace

spring.datasource.primary.jdbc-url=jdbc:mysql://rm-wz96s5izji5099uz13o.mysql.rds.aliyuncs.com:3306/xfz178_com?serverTimezone=UTC&characterEncoding=utf8


## test2 database
#spring.datasource.localdb.jdbc-url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&characterEncoding=utf8
#spring.datasource.localdb.username=root
#spring.datasource.localdb.password=123456
#spring.datasource.localdb.driverClassName=com.mysql.cj.jdbc.Driver



#logging.file.name=./logs/newday-service.log
#日志级别
#logging.file.level.ROOT=DEBUG
#logging.config=classpath:log4j2.xml
logging.config=classpath:logback-spring.xml

redisson.address = redis://127.0.0.1:6379
redisson.password =


#people.beanfactory = PeopleSpringFactory
people.beanfactory = PeopleBeanFactory

 二、加载流程

   1.SpringApplication在Run时,会先预加载环境,即是读取各种配置到环境对象中,然后会广播

ApplicationEnvironmentPreparedEvent消息。
org.springframework.boot.context.event.environmentPrepared
	@Override
	public void environmentPrepared(ConfigurableEnvironment environment) {
		this.initialMulticaster
				.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
	}

2.org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEvent会被触发调用,因为其实现了ApplicationListener会接收事件。

	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
		}
		if (event instanceof ApplicationPreparedEvent) {
			onApplicationPreparedEvent(event);
		}
	}

 3.然后会调用到ConfigFileApplicationListener.postProcessEnvironment,去加载属性配置文件到环境对象。

public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
		addPropertySources(environment, application.getResourceLoader());
	}

protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
		RandomValuePropertySource.addToEnvironment(environment);
		new Loader(environment, resourceLoader).load();
	}

4.在ConfigFileApplicationListener.Loader的内部类中,会初始化两个资源配置文件加载器。properties,yaml

 5.在loader.load方法中会初始化所有的profile,然后再搜索可用的PROFILE配置文件。

	void load() {
			FilteredPropertySource.apply(this.environment, DEFAULT_PROPERTIES, LOAD_FILTERED_PROPERTY,
					(defaultProperties) -> {
						this.profiles = new LinkedList<>();
						this.processedProfiles = new LinkedList<>();
						this.activatedProfiles = false;
						this.loaded = new LinkedHashMap<>();
						initializeProfiles();
						while (!this.profiles.isEmpty()) {
							Profile profile = this.profiles.poll();
							if (isDefaultProfile(profile)) {
								addProfileToEnvironment(profile.getName());
							}
							load(profile, this::getPositiveProfileFilter,
									addToLoaded(MutablePropertySources::addLast, false));
							this.processedProfiles.add(profile);
						}
						load(null, this::getNegativeProfileFilter, addToLoaded(MutablePropertySources::addFirst, true));
						addLoadedPropertySources();
						applyActiveProfiles(defaultProperties);
					});
		}

6. 第二个load方法

		private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
			getSearchLocations().forEach((location) -> {
				boolean isDirectory = location.endsWith("/");
				Set<String> names = isDirectory ? getSearchNames() : NO_SEARCH_NAMES;
				names.forEach((name) -> load(location, name, profile, filterFactory, consumer));
			});
		}

最终读取到的搜索路径为:

 获取搜索文件名,这里注意,如果环境对象中有CONFIG_NAME_PROPERT(spring.config.name)这个配置属性,前面的bootStrap.properties就是通过前一个BootstrapApplicationListener加载的listener,这个对象会在监听到环境准备事件时,设置spring.config.name为bootStrap,然后由当前这个listener来加载配置,则搜索这个文件名,否则搜索默认文件名DEFAULT_NAMES(application):

		private Set<String> getSearchNames() {
			if (this.environment.containsProperty(CONFIG_NAME_PROPERTY)) {
				String property = this.environment.getProperty(CONFIG_NAME_PROPERTY);
				Set<String> names = asResolvedSet(property, null);
				names.forEach(this::assertValidConfigName);
				return names;
			}
			return asResolvedSet(ConfigFileApplicationListener.this.names, DEFAULT_NAMES);
		}

7.接着调用第三个load方法,搜索不同目录下的配置文件。

	private void load(String location, String name, Profile profile, DocumentFilterFactory filterFactory,
				DocumentConsumer consumer) {
	
			Set<String> processed = new HashSet<>();
			for (PropertySourceLoader loader : this.propertySourceLoaders) {
				for (String fileExtension : loader.getFileExtensions()) {
					if (processed.add(fileExtension)) {
						loadForFileExtension(loader, location + name, "." + fileExtension, profile, filterFactory,
								consumer);
					}
				}
			}
		}

8.接着调用第四个load,加载指定扩展名的文件。

	private void loadForFileExtension(PropertySourceLoader loader, String prefix, String fileExtension,
				Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
			DocumentFilter defaultFilter = filterFactory.getDocumentFilter(null);
			DocumentFilter profileFilter = filterFactory.getDocumentFilter(profile);
			if (profile != null) {
				// Try profile-specific file & profile section in profile file (gh-340)
				String profileSpecificFile = prefix + "-" + profile + fileExtension;
				load(loader, profileSpecificFile, profile, defaultFilter, consumer);
				load(loader, profileSpecificFile, profile, profileFilter, consumer);
				// Try profile specific sections in files we've already processed
				for (Profile processedProfile : this.processedProfiles) {
					if (processedProfile != null) {
						String previouslyLoaded = prefix + "-" + processedProfile + fileExtension;
						load(loader, previouslyLoaded, profile, profileFilter, consumer);
					}
				}
			}
			// Also try the profile-specific section (if any) of the normal file
			load(loader, prefix + fileExtension, profile, profileFilter, consumer);
		}

9.接着调用第五个load方法,真正去目录搜索指定文件名和后缀的文件,然后加载到文档。

	private void load(PropertySourceLoader loader, String location, Profile profile, DocumentFilter filter,
				DocumentConsumer consumer) {
			Resource[] resources = getResources(location);
			for (Resource resource : resources) {
				try {
					String name = "applicationConfig: [" + getLocationName(location, resource) + "]";
					List<Document> documents = loadDocuments(loader, name, resource);
				
					List<Document> loaded = new ArrayList<>();
					for (Document document : documents) {
						if (filter.match(document)) {
							addActiveProfiles(document.getActiveProfiles());
							addIncludedProfiles(document.getIncludeProfiles());
							loaded.add(document);
						}
					}
					Collections.reverse(loaded);
					if (!loaded.isEmpty()) {
						loaded.forEach((document) -> consumer.accept(profile, document));
						if (this.logger.isDebugEnabled()) {
							StringBuilder description = getDescription("Loaded config file ", location, resource,
									profile);
							this.logger.debug(description);
						}
					}
				}
				
			}
		}

10.在加载文档时最后会转换文档 。

		private List<Document> asDocuments(List<PropertySource<?>> loaded) {
			if (loaded == null) {
				return Collections.emptyList();
			}
			return loaded.stream().map((propertySource) -> {
				Binder binder = new Binder(ConfigurationPropertySources.from(propertySource),
						this.placeholdersResolver);
				String[] profiles = binder.bind("spring.profiles", STRING_ARRAY).orElse(null);
				Set<Profile> activeProfiles = getProfiles(binder, ACTIVE_PROFILES_PROPERTY);
				Set<Profile> includeProfiles = getProfiles(binder, INCLUDE_PROFILES_PROPERTY);
				return new Document(propertySource, profiles, activeProfiles, includeProfiles);
			}).collect(Collectors.toList());
		}

11.getProfiles(binder, ACTIVE_PROFILES_PROPERTY)这句话,会去从当前读取到的配置文件属性中查找spring.profiles.active属性,然后设置到环境变量。
        这个绑定方法和@configurationProperties中的对象属性绑定原理一致,都是从资源属性列表中逐个资源文件中搜索名称为name的配置。像这里就是spring.profile.active,spring.profile.include

		
private Set<Profile> getProfiles(Binder binder, String name) {

			return binder.bind(name, STRING_ARRAY).map(this::asProfileSet).orElse(Collections.emptySet());
		}

 注意这里的binder不是当前环境变量的binder,而是当前搜索到的配置文件动态生成的BINDER.

Binder binder = new Binder(ConfigurationPropertySources.from(propertySource),
      this.placeholdersResolver);

 现在我们读取application.properties的配置数据了,只有一个。

 12.然后我们接着最后一个load代码,当读取到默认的配置文档后,会再次加载激活和包含的profile配置。

addActiveProfiles(document.getActiveProfiles());
							addIncludedProfiles(document.getIncludeProfiles());
							loaded.add(document);
	void addActiveProfiles(Set<Profile> profiles) {
			this.profiles.addAll(profiles);

			this.activatedProfiles = true;
			removeUnprocessedDefaultProfiles();
		}

此时我们可以看到,已经把dev的profile也加进来了。

 13.最后会把加载到的文档 配置属性回调给消费者函数。

loaded.forEach((document) -> consumer.accept(profile, document));
ConfigFileApplicationListener.addToLoaded就是消费的回调。
private DocumentConsumer addToLoaded(BiConsumer<MutablePropertySources, PropertySource<?>> addMethod,
				boolean checkForExisting) {
			return (profile, document) -> {
				if (checkForExisting) {
					for (MutablePropertySources merged : this.loaded.values()) {
						if (merged.contains(document.getPropertySource().getName())) {
							return;
						}
					}
				}
				MutablePropertySources merged = this.loaded.computeIfAbsent(profile,
						(k) -> new MutablePropertySources());
				addMethod.accept(merged, document.getPropertySource());
			};
		}

这里面的addMethod又是一个回调方法,最终调用到

MutablePropertySources.addLast将这个资源文件对象加载到环境对象的propertList属性中。

设置两个回调的地方在第一个load中,可以找到第一个看代码。

load(profile, this::getPositiveProfileFilter,
      addToLoaded(MutablePropertySources::addLast, false));
	public void addLast(PropertySource<?> propertySource) {
		synchronized (this.propertySourceList) {
			removeIfPresent(propertySource);
			this.propertySourceList.add(propertySource);
		}
	}

 最终属性数据存储在内部类loader

private Map<Profile, MutablePropertySources> loaded 属性中。

14.然后我们再回到第一个load函数,他会不断循环所有的profiles,因为之前已经往这个profile列表中加上dev,所以会再次循环加载dev的profile配置,流程一样。

	while (!this.profiles.isEmpty()) {
							Profile profile = this.profiles.poll();
							if (isDefaultProfile(profile)) {
								addProfileToEnvironment(profile.getName());
							}
							load(profile, this::getPositiveProfileFilter,
									addToLoaded(MutablePropertySources::addLast, false));
							this.processedProfiles.add(profile);
						}

 这是加载dev的profile的配置属性列表。

 然后回调,就会把dev的文档生成资源属性文件添加到loaded列表。

 15.最后会调用addLoadedPropertySources把加载成功的配置属性添加到环境对象的propertySources中。

	private void addLoadedPropertySources() {
			MutablePropertySources destination = this.environment.getPropertySources();
			List<MutablePropertySources> loaded = new ArrayList<>(this.loaded.values());
			Collections.reverse(loaded);
			String lastAdded = null;
			Set<String> added = new HashSet<>();
			for (MutablePropertySources sources : loaded) {
				for (PropertySource<?> source : sources) {
					if (added.add(source.getName())) {
						addLoadedPropertySource(destination, lastAdded, source);
						lastAdded = source.getName();
					}
				}
			}
		}

加载前

 加载后

我们可以看到,是加载到尾部,这也证明了配置文件的优先级最低。同时我们可以看到dev的配置文件是在默认之前。所以会覆盖默认的。

注意上面添加代码,有对loaded作倒序处理。

Collections.reverse(loaded);

至此,配置文件属性加载完毕。 

解析springboot读取application.yml文件
weixin_51495453的博客
12-31 4245
现在开发主要使用微服务框架springboot,在springboot中经常遇到读取application.yml文件的情形。 一、概述 开发过程中经常遇到要读取application.yml文件中的属性值,本文总结几种读取的方式,供参考。 二、详述 我这里使用的是springboot-2.1.2.RELEASE版本,这里使用的是application.properties的配置方式,和使用application.yml的方式是一样的。下面是application.properties文件的内容 cn.co
最全的springbootapplication.properties配置文件详解
Demon丶冷漠
01-04 2560
为方便自己使用,在全网找的最全的application.properties配置文件详解,需要的时候可以来这里找一下配置! 目录 1.网友的配置 2.王军伟老师的总结 1.网友的配置 # REDIS (Redis 配置) # 连接工厂使用的数据库索引 spring.redis.database= 0 # Redis服务器主机 spring.redis.host= # redis服务器端口 spring.redis.port= 6379 # 登录redis服务器的密码 spring.redis..
application-dev.properties
12-26
spring boot 配置文件
SpringBoot读取application.properties文件
weixin_33762130的博客
12-11 352
springboot 配置文件 .properties和.yml的写法区别 例如 :    redis配置的properties或yml文件,如下: spring.redis.cluster.nodes[0]=192.168.0.1:6379   spring.redis.cluster.nodes[1]=192.168.0.2:6379   或   spring:      re...
Springboot启动过程详解
最新发布
o0way0o的博客
08-22 4584
这是一个扩展功能,callRunners(context, applicationArguments) 可以在启动完成后执行自定义的run方法;有2中方式可以实现:a、实现 ApplicationRunner 接口b、实现 CommandLineRunner 接口接下来我们验证一把,为了方便代码可性,我把这2种方式都放在同一个类里面import org。
在Spring Boot中读取application.properties的3种方法
Knight
02-05 2716
在Spring Boot中读取application.properties的3种方法
SpringBoot --- 启动类读取 application.properties 文件配置
yuanchenglong的博客
03-17 4092
    SpringBoot 开发中,在IDEA工具里面新建项目后,会有个启动类,以及配置文件 application.properties。下面小编演示一下,在启动类中读取 application.properties 配置文件。 配置文件: #application.properties 文件配置 string.port=1111 integer.port=1111 db.link.url=jdbc:mysql://localhost:3306/kpl_work db.link.driver=com.
springbootapplication.properties获取常量值为空的解决方案
weixin_45898427的博客
01-12 1068
##工位查询 SearchWkStationCnt.url="http://123"; @RestController @RequestMapping("/a") public class https { @Value("${SearchWkStationCnt.url}") private static String SearchWkStationCnt_url; //@Autowired //private Environment environment; @RequestM
SpringBootapplication.properties的加载
weixin_44601714的博客
09-24 2240
SpringBoot中唯一的配置文件就是application.properties了,那这个配置文件是在什么时候被加载的,存储在什么地方,又是如何被使用的呢?下面从源码的角度来分析 1、application.properties的加载 springboot加载的配置文件是放在environment中的,在prepareEnvironment的时候,springboot读取和加载了applica...
通过源码了解springboot加载application.properties过程
天才小汪汪
09-27 5300
springboot有一个配置文件application.properties,我只知道有这么一个配置文件,但是springboot启动的时候,是在哪里加载该文件的,又如何找到该文件的?从源码去查看 在main方法里执行该方法SpringApplication.run(Test.class, args);查看SpringApplication类的源码,进入run方法 public stati...
springboot对与properties文件中属性设置的路径打包后找不到==》终极解决方案
qq_41948525的博客
09-25 1143
就在前几天,项目中使用的是支付宝的证书方式,需要对这些证书放入静态文件中留存。我们都知道,本地测试是完全没用问题的,路径直接是src/**,本地测试完全可以找到。但是打成jar之后,就不再有这个src目录了,而是在classes目录下。可是在服务器也得获取到这些证书咋办呢? 我尝试过很多种方法: 1:将这些证书放入资源服务器,想直接拿解析出来的URL给支付宝来解析这个url中的文本内容,可以结果不尽人意。请看下面源码: 可以看到,支付宝工具类中是直接将你返回给他的字符串以文件来解析,可是这个File并
SpringBoot获得application.properties中数据的几种方式
m0_67393686的博客
04-26 1304
SpringBoot获得application.properties中数据的几种方式 第一种方式 [html] view plain copy @SpringBootApplication publicclassSpringBoot01Application{ publicstaticvoidmain(String[]args){ ConfigurableApplicationContextcontext=SpringApplication.run(SpringBoot01Applicati
Spring读取properties文件的值
qq_37129192的博客
12-28 1654
properties文件读取方式
Springboot配置文件中properties,yml,yaml
Wdoing的博客
10-24 652
properties,yml配置文件的基础知识
spring-boot-starter-parent_SpringBoot2系列教程(二)解析springbootstarterparent作用
weixin_39845113的博客
11-26 363
前言上一节我们初步认识了SpringBoot是什么,以及使用SpringBoot快速搭建了第一个应用程序,我们会发现使用SpringBoot快速搭建Spring框架是非常快速的,因为省略了不必要的各种xml配置文件的配置,这些配置都交给了SpringBoot帮我们自动配置了。同时,上一节我们演示了使用三种不同的工具进行创建SpringBoot项目,我们发现不管使用哪一种方法创建Sprin...
SpringBoot (配置文件)
08-15 352
1 简介 SpringBoot中免除了大部分手动配置,但是对于一些特定的情况,还是需要我们进行手动配置的,SpringBoot为我们提供了application.properties配置文件,让我们可以进行自定义配置,来对默认的配置进行修改,以适应具体的生产情况,当然还包括一些第三方的配置。几乎所有配置都可以写到application.peroperties文件中,这个文件会被SpringBoot自动加载,免去了我们手动加载的烦恼。 1、配置文件的格式   SpringBoot可以识别两种...
Spring Boot最常用的3种读取properties配置文件中数据的方法:
job_csdn的博客
01-07 2391
此处为图片。图下可复制代码。 1、使用@Value注解读取 读取properties配置文件时,默认读取的是application.propertiesapplication.properties: demo.name=Name demo.age=18 Java代码: import org.springframework.beans.factory.a...
springbootspringboot读取application配置文件
Mrerlou的博客
05-27 1911
项目需求 项目需要读取application.yml中自定义的配置文件。 跨工程也是可以读取application.yml文件的配置内容的 读取方式 @Value Environment 方式一:使用@Value方式(常用) 核心配置文件application.yml内容如下: # 自定义配置项 uuap: server: host: 10.12.16.84 systoken: 39ca7b2c849b85d1 sysname: sitonya 代码示意: @Serv
springboot读取application.properties的值
09-05
Spring Boot读取application.properties的值的方式有多种方法。一种常用的方式是通过使用@Value注解来注入属性值。可以在需要使用属性值的字段、方法的参数、方法的返回值上添加@Value注解,并指定要注入的属性的键名。例如,可以使用@Value("${spring.rabbitmq.host}")来注入application.properties文件中的spring.rabbitmq.host属性的值。这样,在程序运行时,Spring Boot会自动读取属性文件中的值,并将其注入到相应的位置。 另一种方式是使用PropertiesLoaderUtils类来读取属性文件的值。首先,需要导入java.util.Properties和org.springframework.core.io.support.PropertiesLoaderUtils类。然后,可以使用PropertiesLoaderUtils的loadProperties方法来加载属性文件,然后使用getProperty方法获取具体的属性值。例如,可以使用Properties properties = PropertiesLoaderUtils.loadProperties(new ClassPathResource("application.properties"))来加载application.properties文件,然后使用properties.getProperty("spring.rabbitmq.host")来获取spring.rabbitmq.host属性的值。 总结起来,Spring Boot提供了多种方式来读取application.properties文件的值,可以根据具体的需求选择适合的方式来获取属性值。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring Boot中配置文件application.properties使用](https://download.csdn.net/download/weixin_38672800/12765190)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [SpringBoot获得application.properties中数据的几种方式](https://blog.csdn.net/m0_67393686/article/details/124421983)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [SpringBoot读取application.properties配置文件](https://blog.csdn.net/watson2017/article/details/124732267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
写文章

热门文章

  • 在Windows下编译FFmpeg详细说明 12497
  • rtmp推流直播流程 8417
  • netty 管道和handler的加载和处理流程 7676
  • Redisson 管道批量发送命令流程分析 5951
  • spring @order控制对象的顺序 5722

分类专栏

  • web spring 15篇
  • 分布式事务 2篇
  • mongodb 1篇
  • 踩坑记录 4篇
  • nacos
  • 线上集群问题处理记录
  • redis 4篇
  • 后台登录认证中间件 1篇
  • spring boot 9篇
  • spring cloud 6篇
  • java并发 1篇
  • netty 8篇
  • WINCE程序开发 13篇
  • ANDROID应用开发 9篇
  • WIFI 关联 认证 1篇

最新评论

  • spring BeanPostProcessor,BeanFactoryPostProcessor作用

    CSDN-Ada助手: SpringBoot项目里,如何做异步计算,异步计算超时和异常处理你会怎么做呢?

  • springcloud alibaba 整合seata的TCC

    CSDN-Ada助手: 推荐 Java 技能树:https://edu.csdn.net/skill/java?utm_source=AI_act_java

  • mongodb分片集群搭建踩坑记录

    乘风破浪的码农: 估计不行了,要重新建新的,然后迁移数据

  • mongodb分片集群搭建踩坑记录

    万分之一甜: 设置为范围分片了 还能更改为hash 吗?

  • springboot-rocketmq整合NOT_CONSUME_YET问题处理

    disguiser_9: 改了之后还是那样呢

大家在看

  • ctfshow(259->261)--反序列化漏洞--原生类与更多魔术方法
  • -- 1149. 文章浏览 II 2
  • 浏览器运行过程以及过程中需要关注的事 1066
  • 第六章元素应用CSS 1215
  • C语言(一维数组)

最新文章

  • Nacos2.1.0 && 2.2.3服务注册流程分析
  • nacos获取服务实例流程
  • nacos服务注册流程
2024年4篇
2023年3篇
2022年9篇
2021年37篇
2016年10篇
2014年2篇
2013年11篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家大型玻璃钢龙雕塑上海季节性商场美陈衡水玻璃钢海豚雕塑厂家无锡玻璃钢人物雕塑厂家直销杭州玻璃钢花盆研发玻璃钢雕塑开裂是正常现象吗南海玻璃钢雕塑山西玻璃钢雕塑雨花玻璃钢卡通雕塑扬州广场玻璃钢雕塑锦州玻璃钢雕塑价格爱丽丝梦游仙境商场美陈济南卡通玻璃钢雕塑订制揭阳革命主题玻璃钢人物雕塑商场火烈鸟美陈灯塔市鹏铭玻璃钢雕塑厂辽宁玻璃钢仿铜雕塑价格乐从玻璃钢人物雕塑业界口碑好玻璃钢浮雕塑浏阳玻璃钢卡通雕塑封开玻璃钢造型雕塑富阳玻璃钢花盆花器西瓜玻璃钢雕塑多少钱玻璃钢铜象老人雕塑威海人物玻璃钢雕塑厂家深圳玻璃钢雕塑设计公司上饶步行街玻璃钢雕塑优势菏泽佛像玻璃钢雕塑广州玻璃钢卡通雕塑摆件北京室内商场美陈供货商香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化