目录
上章《hualinux spring 3.4:idea 2020.1 创建简单的spring》讲了如果使用iidea创建spring项目,并写了一个简单的helloWorld,现在这里基于这个项目讲依赖注入。
一、普通测试
在测试之前我把《hualinux spring 3.4:idea 2020.1 创建简单的spring》建立的java文件及xml配置文件全部删除,恢复空项目
1.1 建立无参hello
1.1.1 建立配置文件
src右击-->new-->XML Configuration File-->Spring config-->输入名字“ApplicationContext”
ApplicationContext.xml配置文件如下:
<!--配置bean-->
<bean id="hello" class="com.hualinux.beans.Hello">
<property name="name" value="Spring"/>
</bean>
1.1.2 代码
src-->com.hualinux.beans.Hello.java
package com.hualinux.beans;
public class Hello {
String name;
public void helloTest(){
System.out.println("你好:"+name);
}
public void setName(String name) {
this.name = name;
}
}
src-->com.hualinux.beans.Main.java
package com.hualinux.beans;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//1. 创建 Spring 的 IOC 容器对象
ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
//2. 从IOC容器中获取Bean实例
Hello hello= (Hello) ctx.getBean("hello");
//3. 调用hello方法
hello.helloTest();
}
}
1.1.3 运行结果
运行一下,怎运行前一章已经讲了,我这里就不说了
1.1.4 总结
在spring的xml配置中:
id:Bean 的名称。
- 在 IOC 容器中必须是唯一的
- 若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字
- id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔
Spring ApplicationContext 容器
Application Context 是 spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。 另外,它增加了企业所需要的功能,比如,从属性文件中解析文本信息和将事件传递给所指定的监听器。这个容器在 org.springframework.context.ApplicationContext interface 接口中定义。
ApplicationContext 包含 BeanFactory 所有的功能,一般情况下,相对于 BeanFactory,ApplicationContext 会更加优秀。当然,BeanFactory 仍可以在轻量级应用中使用,比如移动设备或者基于 applet 的应用程序。
最常被使用的 ApplicationContext 接口实现:
- FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。
- ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
- WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
1.2 建立有参的hello
如果修改为有参的构造器得需要一个默认的无参构造器
//用idea测试发现不加也行,但建议还是加上
复制Hello.java变成Hello2.java
public class Hello2 {
String name;
public void helloTest(){
System.out.println("你好:"+name);
}
public Hello2() {
}
public Hello2(String name) {
this.name = name;
}
}
ApplicationContext.xml配置文件添加如下内容
<!--配置bean-->
<bean id="hello2" class="com.hualinux.beans.Hello2">
<constructor-arg name="name" value="Spring2"/>
</bean>
Main.java,修改如下:
package com.hualinux.beans;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//1. 创建 Spring 的 IOC 容器对象
ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
//2. 从IOC容器中获取Bean实例
Hello hello= (Hello) ctx.getBean("hello");
Hello2 hello2= (Hello2) ctx.getBean("hello2");
//3. 调用hello方法
hello.helloTest();
hello2.helloTest();
}
}
运行结果为:
二、 属性注入
2.1 get和set注入
属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值
属性注入是实际应用中最常用的注入方式
例子就是上面的无参hello
2.2 ref引用
- 组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能. 要使 Bean 能够相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用
- 在 Bean 的配置文件中, 可以通过 <ref> 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用.
- 也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean
下面是一个配置例子,需要建立Car类,并有3个属性;也需要建立Person类,3个属性,其中一个包括car ,后面将贴出代码
<bean id="car" class="com.hualinux.beans.Car">
<constructor-arg value="BMW X6" />
<constructor-arg value="进口宝马" />
<constructor-arg value="1000000" />
</bean>
<bean id="person" class="com.hualinux.beans.Person" >
<property name="name" value="华" />
<property name="age" value="20" />
<property name="car" ref="car" />
</bean>
三、构造函数注入
通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。
构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中没有 name 属性
3.1 默认
例子1,上面的hello2
例子2:
src-->com.hualinux.beans.Car.java
package com.hualinux.beans;
public class Car {
private String brand;
private String corp;
private float price;
private int maxSpeed;
// 先弄3个参数,最后一个不用
public Car(String brand, String corp, float price) {
this.brand = brand;
this.corp = corp;
this.price= price;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", corp='" + corp + '\'' +
", price=" + price +
", maxSpeed=" + maxSpeed +
'}';
}
}
ApplicationContext.xml配置文件
<!--通过构造方法来配置 bean的属性-->
<!--为了方便先弄三个参数的-->
<bean id="car" class="com.hualinux.beans.Car">
<constructor-arg value="BMW X6" />
<constructor-arg value="进口宝马" />
<constructor-arg value="1000000"/>
</bean>
Main.java
package com.hualinux.beans;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//1. 创建 Spring 的 IOC 容器对象
ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
//2. 从IOC容器中获取Bean实例
Hello hello= (Hello) ctx.getBean("hello");
Hello2 hello2= (Hello2) ctx.getBean("hello2");
Car car= (Car) ctx.getBean("car");
System.out.println(car.toString());
//3. 调用hello方法
hello.helloTest();
hello2.helloTest();
}
}
运行结果为:
3.2使用index索引匹配入参
ApplicationContext.xml配置文件中id为car的修改为如下:
<!--索引方式-->
<bean id="car" class="com.hualinux.beans.Car">
<constructor-arg value="BMW X6" index="0" />
<constructor-arg value="进口宝马" index="1" />
<constructor-arg value="1000000" index="2"/>
</bean>
再次运行Main.java,结果如下:
3.3 按类型匹配入参
ApplicationContext.xml配置文件中id为car的修改为如下:
<bean id="car" class="com.hualinux.beans.Car">
<constructor-arg value="BMW X6" type="java.lang.String"/>
<constructor-arg value="进口宝马" type="java.lang.String" />
<constructor-arg value="1000000" type="float"/>
</bean>
运行Main.java 结果也是相同的
3.4 问题 相同class
src-->com.hualinux.beans.Car.java 建立多一个构造函数
// 不使用第3个属性
public Car(String brand, String corp, int maxSpeed) {
this.brand = brand;
this.corp = corp;
this.maxSpeed = maxSpeed;
}
ApplicationContext.xml配置文件中添加:
<bean id="car2" class="com.hualinux.beans.Car">
<constructor-arg value="法拉利" />
<constructor-arg value="进口" />
<constructor-arg value="320" />
</bean>
这样才有2个car了
<bean id="car2" class="com.hualinux.beans.Car">
<constructor-arg value="法拉利" />
<constructor-arg value="进口" />
<constructor-arg value="320" />
</bean>
<bean id="car" class="com.hualinux.beans.Car">
<constructor-arg value="BMW X6" type="java.lang.String"/>
<constructor-arg value="进口宝马" type="java.lang.String" />
<constructor-arg value="1000000" type="float"/>
</bean>
Main添加多一个car2,总代码如下:
package com.hualinux.beans;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//1. 创建 Spring 的 IOC 容器对象
ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
//2. 从IOC容器中获取Bean实例
Hello hello= (Hello) ctx.getBean("hello");
Hello2 hello2= (Hello2) ctx.getBean("hello2");
Car car= (Car) ctx.getBean("car");
System.out.println(car.toString());
Car car2= (Car) ctx.getBean("car2");
System.out.println(car2.toString());
//3. 调用hello方法
hello.helloTest();
hello2.helloTest();
}
}
结果:320是时速即变成了价格吧
解决方法:
指定type匹配类型也行(因为2个构造函数,用的是重载)
注:用index固定好参数顺序是不行的
<!-- 使用构造器注入值可以指定参数的位置和参数类型!以区分重载构造器!-->
<bean id="car2" class="com.hualinux.beans.Car">
<constructor-arg value="法拉利" type="java.lang.String" />
<constructor-arg value="进口" type="java.lang.String" />
<constructor-arg value="320" type="int"/>
</bean>
再次运行发现正常了,如下图所示:
四、 其它
4.1字面值
- 字面值:可用字符串表示的值,可以通过 <value> 元素标签或 value 属性进行注入。
- 基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式
- 若字面值中包含特殊字符,可以使用 <![CDATA[]]> 把字面值包裹起来。
4.2 内部bean
- 当 Bean 实例仅仅给一个特定的属性使用时, 可以将其声明为内部 Bean. 内部 Bean 声明直接包含在 <property> 或 <constructor-arg> 元素里, 不需要设置任何 id 或 name 属性
- 内部 Bean 不能使用在任何其他地方
4.2.1 例子
src-->com.hualinux.beans.Person.java
package com.hualinux.beans;
public class Person {
private String name;
private int age;
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public Person() {
}
public Person(String name, int age, Car car) {
this.name = name;
this.age = age;
this.car = car;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
'}';
}
}
ApplicationContext.xml配置文件中添加:
<!-- 内部bean,不能补外部引用,只能内部使用 -->
<bean id="person" class="com.hualinux.beans.Person" >
<property name="name" value="华" />
<property name="age" value="20" />
<property name="car">
<bean id="car3" class="com.hualinux.beans.Car">
<constructor-arg value="慕尚" />
<constructor-arg value="进口宾利" />
<constructor-arg value="305" type="int" />
</bean>
</property>
</bean>
Main.java中添加如下配置
//在Main中添加
Person person= (Person) ctx.getBean("person");
System.out.println(person.toString());
运行结果为:
4.3 null值和级联属性
- 可以使用专用的 <null/> 元素标签为 Bean 的字符串或其它对象类型的属性注入 null 值
- 和 Struts、Hiberante 等框架一样,Spring 支持级联属性的配置。
ApplicationContext.xml配置文件中添加:
<bean id="person2" class="com.hualinux.beans.Person" >
<property name="name" value="华2" />
<property name="age" value="20" />
<!-- 测试赋值null -->
<property name="car" ><null/></property>
</bean>
或
<bean id="person2" class="com.hualinux.beans.Person" >
<constructor-arg value="华2" />
<constructor-arg value="20" />
<!-- 测试赋值null -->
<constructor-arg ><null/></constructor-arg>
</bean>
Main.jva添加
Person person2= (Person) ctx.getBean("person2");
System.out.println(person2.toString());
运行结果:
级联属性赋值:
修改ApplicationContext.xml配置文件中的person2
为了方便我在Car.java中添加了getter和setter方法
<bean id="person2" class="com.hualinux.beans.Person" >
<constructor-arg value="华2" />
<constructor-arg value="20" />
<!-- 测试赋值null -->
<!--<constructor-arg ><null/></constructor-arg>-->
<!-- 级联属性赋值。注意:属性需要先初始化才可以为级联属性赋值,否则会有异常,和struts2不同-->
<constructor-arg ref="car"/>
<!-- Car类中的maxSpeed要添加setter方法,否则不生效-->
<property name="car.maxSpeed" value="250"/>
</bean>
4.4 集合属性
- 在 Spring中可以通过一组内置的 xml 标签(例如: <list>, <set> 或 <map>) 来配置集合属性.
- 配置 java.util.List 类型的属性, 需要指定 <list> 标签, 在标签里包含一些元素. 这些标签可以通过 <value> 指定简单的常量值, 通过 <ref> 指定对其他 Bean 的引用. 通过<bean> 指定内置 Bean 定义. 通过 <null/> 指定空元素. 甚至可以内嵌其他集合.
- 数组的定义和 List 一样, 都使用 <list>
- 配置 java.util.Set 需要使用 <set> 标签, 定义元素的方法与 List 一样.
src-->com.hualinux.beans.collection.Car.java(和src-->com.hualinux.beans.Car.java一样)
package com.hualinux.beans.collection;
public class Car {
private String brand;
private String corp;
private float price;
private int maxSpeed;
// 先弄3个参数,最后一个不用
public Car(String brand, String corp, float price) {
this.brand = brand;
this.corp = corp;
this.price= price;
}
// 不使用第3个属性
public Car(String brand, String corp, int maxSpeed) {
this.brand = brand;
this.corp = corp;
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", corp='" + corp + '\'' +
", price=" + price +
", maxSpeed=" + maxSpeed +
'}';
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getCorp() {
return corp;
}
public void setCorp(String corp) {
this.corp = corp;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
}
src-->com.hualinux.beans.collection.Person.java如下:
package com.hualinux.beans.collection;
import java.util.List;
public class Person {
private String name;
private int age;
private List<com.hualinux.beans.collection.Car> car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<com.hualinux.beans.collection.Car> getCar() {
return car;
}
public void setCar(List<com.hualinux.beans.collection.Car> car) {
this.car = car;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
'}';
}
}
src右击-->new-->XML Configuration File-->Spring config-->输入名字“collection“
<bean id="car" class="com.hualinux.beans.collection.Car">
<constructor-arg value="BMW X6" />
<constructor-arg value="进口宝马" />
<constructor-arg value="1000000" />
</bean>
<!-- 使用构造器注入值可以指定参数的位置和参数类型!以区分重载构造器!-->
<bean id="car2" class="com.hualinux.beans.collection.Car">
<constructor-arg value="法拉利" index="0" />
<constructor-arg value="进口" index="1" />
<constructor-arg value="320" index="2" />
</bean>
<bean id="car3" class="com.hualinux.beans.collection.Car">
<constructor-arg value="911" type="java.lang.String" />
<constructor-arg value="进口保时捷" type="java.lang.String" />
<constructor-arg value="340" type="int" />
</bean>
<bean id="person3" class="com.hualinux.beans.collection.Person">
<property name="name" value="Mike"/>
<property name="age" value="27"/>
<property name="car">
<list>
<ref bean="car" />
<ref bean="car2" />
<ref bean="car3" />
</list>
</property>
</bean>
src-->com.hualinux.beans.collection.Main.java
package com.hualinux.beans.collection.com.hualinux.beans.collection;
import com.hualinux.beans.collection.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("collection.xml");
// 这里的Person为com.hualinux.beans.collection.Person
Person person= (Person) ctx.getBean("person3");
System.out.println(person.toString());
}
}
运行结果:
Person{name='Mike', age=27, car=[Car{brand='BMW X6', corp='进口宝马', price=1000000.0, maxSpeed=0}, Car{brand='法拉利', corp='进口', price=320.0, maxSpeed=0}, Car{brand='911', corp='进口保时捷', price=0.0, maxSpeed=340}]}
4.5 集合属性
- Java.util.Map 通过 <map> 标签定义, <map> 标签里可以使用多个 <entry> 作为子标签. 每个条目包含一个键和一个值.
- 必须在 <key> 标签里定义键
- 因为键和值的类型没有限制, 所以可以自由地为它们指定 <value>, <ref>, <bean> 或 <null> 元素.
- 可以将 Map 的键和值作为 <entry> 的属性定义: 简单常量使用 key 和 value 来定义; Bean 引用通过 key-ref 和 value-ref 属性定义
- 使用 <props> 定义 java.util.Properties, 该标签使用多个 <prop> 作为子标签. 每个 <prop> 标签必须定义 key 属性.
src-->com.hualinux.beans.collection.MapPerson.java
package com.hualinux.beans.collection;
import java.util.Map;
public class MapPerson {
private String name;
private int age;
private Map<String,Car> cars;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Map<String, Car> getCars() {
return cars;
}
public void setCars(Map<String, Car> cars) {
this.cars = cars;
}
@Override
public String toString() {
return "MapPerson{" +
"name='" + name + '\'' +
", age=" + age +
", cars=" + cars +
'}';
}
}
collection.xml配置文件中添加如下内容
<!-- 配置Map属性值 -->
<bean id="mapPerson" class="com.hualinux.beans.collection.MapPerson">
<property name="name" value="Rose" />
<property name="age" value="28" />
<property name="cars">
<!-- 使用map节点及map的entry子节点配置Map类型成员变更-->
<map>
<entry key="AA" value-ref="car"/>
<entry key="BB" value-ref="car2" />
</map>
</property>
</bean>
com.hualinux.beans.collection.Main.java是main中添加
MapPerson mapPerson= (MapPerson) ctx.getBean("mapPerson");
System.out.println(mapPerson);
运行结果如下:
Person{name='Mike', age=27, car=[Car{brand='BMW X6', corp='进口宝马', price=1000000.0, maxSpeed=0}, Car{brand='法拉利', corp='进口', price=320.0, maxSpeed=0}, Car{brand='911', corp='进口保时捷', price=0.0, maxSpeed=340}]}
MapPerson{name='Rose', age=28, cars={AA=Car{brand='BMW X6', corp='进口宝马', price=1000000.0, maxSpeed=0}, BB=Car{brand='法拉利', corp='进口', price=320.0, maxSpeed=0}}}
例2 模拟数据库配置连接
src-->com.hualinux.beans.collection.DataSource.java
package com.hualinux.beans.collection;
import java.util.Properties;
public class DataSource {
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "DataSource{" +
"properties=" + properties +
'}';
}
}
collection.xml配置文件中添加
<!-- 配置 Properties 属性值 -->
<bean id="dataSource" class="com.hualinux.beans.collection.DataSource">
<property name="properties">
<!-- 使用 props 和 prop 子节点来为 properties 属性赋值-->
<props>
<prop key="user">root</prop>
<prop key="password">root</prop>
<prop key="jdbcUrl">jdbc:mysql://test</prop>
<prop key="driverClass">com.mysql.jdbc.Driver</prop>
</props>
</property>
</bean>
com.hualinux.beans.collection.Main.java,的main中添加,如下代码:
DataSource dataSource= (DataSource) ctx.getBean("dataSource");
System.out.println(dataSource.getProperties());
运行结果:
Person{name='Mike', age=27, car=[Car{brand='BMW X6', corp='进口宝马', price=1000000.0, maxSpeed=0}, Car{brand='法拉利', corp='进口', price=320.0, maxSpeed=0}, Car{brand='911', corp='进口保时捷', price=0.0, maxSpeed=340}]}
MapPerson{name='Rose', age=28, cars={AA=Car{brand='BMW X6', corp='进口宝马', price=1000000.0, maxSpeed=0}, BB=Car{brand='法拉利', corp='进口', price=320.0, maxSpeed=0}}}
{password=root, driverClass=com.mysql.jdbc.Driver, jdbcUrl=jdbc:mysql://test, user=root}
4.6 使用 utility scheme 定义集合
- 使用基本的集合标签定义集合时, 不能将集合作为独立的 Bean 定义, 导致其他 Bean 无法引用该集合, 所以无法在不同 Bean 之间共享集合.
- 可以使用 util schema 里的集合标签定义独立的集合 Bean. 需要注意的是, 必须在 <beans> 根元素里添加 util schema 定义
collection.xml配置文件中添加
<!-- 配置单例集合bean,以供多个bean进行引用,需要导入util 命名空间-->
<util:list id="cars">
<ref bean="car" />
<ref bean="car2" />
</util:list>
<bean id="person4" class="com.hualinux.beans.collection.Person">
<property name="name" value="Jack"/>
<property name="age" value="29"/>
<property name="car" ref="cars"/>
</bean>
list会提示到不到,点一下按Alt+Enter
这后就显示正常了
4.7 使用p命名空间
- 为了简化 XML 文件的配置,越来越多的 XML 文件采用属性而非子元素配置信息。
- Spring 从 2.5 版本开始引入了一个新的 p 命名空间,可以通过 <bean> 元素属性的方式配置 Bean 的属性。
- 使用 p 命名空间后,基于 XML 的配置方式将进一步简化
collection.xml配置文件中添加
<!-- 通过p命名空间为bean的属性赋值,需要先导入p命名空间。相于于传统配置方式更加简洁 -->
<bean id="person5" class="com.hualinux.beans.collection.Person"
p:name="Queen" p:car-ref="cars" />
上面p是红色的话用Alt+Enter就会自动为配置添加相关的关联,这样p命名空间就可以使用了。
com.hualinux.beans.collection.Main.java,的main中添加,如下代码:
Person person5= (Person) ctx.getBean("person5");
System.out.println(person5.toString());
运行结果为:
Person{name='Mike', age=27, car=[Car{brand='BMW X6', corp='进口宝马', price=1000000.0, maxSpeed=0}, Car{brand='法拉利', corp='进口', price=320.0, maxSpeed=0}, Car{brand='911', corp='进口保时捷', price=0.0, maxSpeed=340}]}
MapPerson{name='Rose', age=28, cars={AA=Car{brand='BMW X6', corp='进口宝马', price=1000000.0, maxSpeed=0}, BB=Car{brand='法拉利', corp='进口', price=320.0, maxSpeed=0}}}
{password=root, driverClass=com.mysql.jdbc.Driver, jdbcUrl=jdbc:mysql://test, user=root}
Person{name='Queen', age=0, car=[Car{brand='BMW X6', corp='进口宝马', price=1000000.0, maxSpeed=0}, Car{brand='法拉利', corp='进口', price=320.0, maxSpeed=0}]}