属性配置细节
1.【属性值注入还可以用value节点进行注入】
2.【字面值】
(1)字面值:可用字符串表示的值,可以通过<value>元素标签或value属性进行注入。
(2)基本数据类型及其封装类、String等类型都可以采取字面值注入的方式。
(3)若字面值中包含特殊字符,可以使用<![CDATA[]]>把字符值包裹起来。
举栗子:
运行结果:
【3.引用其他的bean】
(1)组成应用程序的Bean经常需要相互协作以完成应用程序的功能。要使Bean能够相互访问,就必须在Bean配置文件中指定对Bean的引用。
(2)在Bean的配置文件中,可以通过<ref>元素或者ref属性为Bean的属性或者构造器参数指定对Bean的引用。
<ref>元素:
ref属性:
(3)也可以在属性或构造器里包含Bean的声明,这样的Bean称为内部Bean。
当Bean实例仅仅给一个特定的属性使用时,可以将其声明为内部Bean。内部Bean声明直接包含在<property>或<constructor-arg>元素里,不需要设置任何id或name属性。
内部Bean不能使用在任何地方。
1 <!-- 内部bean ,不能被外部引用,只能在内部使用--> 2 <property name="car"> 3 <bean class="com.hk.beans.Car"> 4 <constructor-arg value="Ford"></constructor-arg> 5 <constructor-arg value="ChangAn"></constructor-arg> 6 <constructor-arg value="200000" type="double"></constructor-arg> 7 </bean> 8 </property>
【中途解决bug】
1 九月 05, 2018 2:48:22 下午 org.springframework.context.support.ClassPathXmlApplicationContext refresh 2 警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person2' defined in class path resource [applicationContext.xml]: Unsatisfied dependency expressed through constructor parameter 2: Could not convert argument value of type [java.lang.String] to required type [com.hk.beans.Car]: Failed to convert value of type [java.lang.String] to required type [com.hk.beans.Car]; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.hk.beans.Car]: no matching editors or conversion strategy found 3 Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person2' defined in class path resource [applicationContext.xml]: Unsatisfied dependency expressed through constructor parameter 2: Could not convert argument value of type [java.lang.String] to required type [com.hk.beans.Car]: Failed to convert value of type [java.lang.String] to required type [com.hk.beans.Car]; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.hk.beans.Car]: no matching editors or conversion strategy found 4 at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723) 5 at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) 6 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1148) 7 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1051) 8 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 9 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 10 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 11 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 12 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 13 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 14 at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751) 15 at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) 16 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) 17 at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) 18 at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83) 19 at com.hk.beans.Main.main(Main.java:20)
代码错误定位到Main.java中的:
1 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
翻译错误:
1 ClassPathXmlApplicationContext刷新 2 警告:上下文初始化期间遇到的例外——取消刷新尝试:org.springframework.beans.factory。不满足的依赖异常:在类路径资源applicationContext中定义的名称“person2”错误创建bean。xml:通过构造器参数2表达不满意的依赖性:不能转换类型java.lang的参数值。字符串到需要的类型com.hk.bean。Car:未能转换类型java.lang的值。字符串到所需的类型com.hk.beans.car;嵌套异常是java.lang。非法状态例外:不能转换类型java.lang的值。字符串到需要的类型com.hk.bean。Car:没有匹配的编辑器或转换策略 3 线程“main”。springframework.beans.factory。不满足的依赖异常:在类路径资源applicationContext中定义的名称“person2”错误创建bean。xml:通过构造器参数2表达不满意的依赖性:不能转换类型java.lang的参数值。字符串到需要的类型com.hk.bean。Car:未能转换类型java.lang的值。字符串到所需的类型com.hk.beans.car;嵌套异常是java.lang。非法状态例外:不能转换类型java.lang的值。字符串到需要的类型com.hk.bean。Car:没有匹配的编辑器或转换策略 4 org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723) 5 org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) 6 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1148) 7 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1051) 8 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 9 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 10 在1.美元org.springframework.beans.factory.support.AbstractBeanFactory getobject(AbstractBeanFactory.java:306) 11 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 12 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 13 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 14 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751) 15 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) 16 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) 17 在org.springframework.context.support.ClassPathXmlApplicationContext。< init >(ClassPathXmlApplicationContext.java:139) 18 在org.springframework.context.support.ClassPathXmlApplicationContext。< init >(ClassPathXmlApplicationContext.java:83) 19 com.hk.beans.Main.main(Main.java:20)
最后发现,是配置文件中的一个构造器属性错误:
解决:应该将value改为ref,粗心大意了 +_+。
【4.注入参数:null值和级联属性】
(1)可以用专用的<null/>元素标签为Bean的字符串或其他对象类型的属性注入null值。
测试:
1 <bean id="person2" class="com.hk.beans.Person"> 2 <constructor-arg value="student" ></constructor-arg> 3 <constructor-arg value="25"></constructor-arg> 4 <!-- 5 <constructor-arg ref="car"></constructor-arg> 6 --> 7 <!-- 测试赋值null --> 8 <constructor-arg><null/></constructor-arg> 9 </bean>
运行结果:
(2)和Struts、Hibernate等框架一样,Spring支持级联属性的配置。
1 <constructor-arg ref="car"></constructor-arg> 2 <!-- 为级联属性赋值 ,注意;属性需要先初始化后才可以为级联属性赋值,否则会有异常,和Struts2不同。--> 3 <property name="car.maxSpeed" value="300000"></property>
以上代码可知,先给car赋值,再给car的属性maxSpeed赋值。
问题:如果先不给car赋值,直接给maxSpeed赋值,会行的通吗?试验一下--->
1 <bean id="person" class="com.hk.beans.Person"> 2 <property name="name" value="xskb"></property> 3 <property name="age" value="22"></property> 4 <!-- 内部bean ,不能被外部引用,只能在内部使用--> 5 <!-- 6 <property name="car"> 7 <bean class="com.hk.beans.Car"> 8 <constructor-arg value="Ford"></constructor-arg> 9 <constructor-arg value="ChangAn"></constructor-arg> 10 <constructor-arg value="200000" type="double"></constructor-arg> 11 </bean> 12 </property> 13 --> 14 <property name="car.maxSpeed" value="260"></property> 15 </bean>
上述配置文件代码,没有给car赋值,直接给car的属性maxSpeed赋值,跑一下,有bug,如下:
1 Caused by: org.springframework.beans.NullValueInNestedPathException: Invalid property 'car' of bean class [com.hk.beans.Person]: Value of nested property 'car' is null
但是,当先给car赋值,再给car的属性赋值,就没有错误了。
1 <bean id="person" class="com.hk.beans.Person"> 2 <property name="name" value="xskb"></property> 3 <property name="age" value="22"></property> 4 <!-- 内部bean ,不能被外部引用,只能在内部使用--> 5 <property name="car"> 6 <bean class="com.hk.beans.Car"> 7 <constructor-arg value="Ford"></constructor-arg> 8 <constructor-arg value="ChangAn"></constructor-arg> 9 <constructor-arg value="200000" type="double"></constructor-arg> 10 </bean> 11 </property> 12 <property name="car.maxSpeed" value="260"></property> 13 </bean>
运行结果:
【5.集合属性】
(1)在Spring中,可以通过一组内置的XML标签(例如:<List>,<set>,<map>)来配置集合属性。
(2)配置java.util.List类型的属性,需要指定<list>标签,在标签里包含一些元素。这些标签可以通过<value>指定简单的常量值,通过<ref>指定对其他Bean的引用。通过<bean>指定内置Bean定义。通过<null/>指定空元素。甚至可以内嵌其他组合。
(3)数组的定义和List一样,都使用<List>。
(4)配置java.util.Set需要使用<set>标签,定义元素的方法与List一样。
配置java.util.List类型的属性,需要指定<list>标签,在标签里包含一些元素。这些标签可以通过<value>指定简单的常量值,通过<ref>指定对其他Bean的引用:
1 <!-- 测试如何配置集合属性 --> 2 <bean id="person3" class="com.hk.beans.collections.Person"> 3 <property name="name" value="Mike"></property> 4 <property name="age" value="25"></property> 5 <property name="cars" > 6 <!-- 使用List节点为List类型的属性赋值 --> 7 <list> 8 <ref bean="car"/> 9 <ref bean="car2"/> 10 </list> 11 </property> 12 </bean>
运行结果:
1 HelloWorld's Constructor... 2 setName:Spring 3 Person [name=Mike, age=25, cars=[Car [brand=BWM, corp=ShangHai, price=100000.0, maxSpeed=300000], Car [brand=bieke, corp=<ShangHai**>, price=0.0, maxSpeed=250]]]
通过<bean>指定内置Bean定义:
运行结果;
1 HelloWorld's Constructor... 2 setName:Spring 3 Person [name=Mike, age=25, cars=[Car [brand=BWM, corp=ShangHai, price=100000.0, maxSpeed=300000], Car [brand=bieke, corp=<ShangHai**>, price=0.0, maxSpeed=250], Car [brand=Ford, corp=ChangAn, price=200000.0, maxSpeed=0]]]
(5)Java.util.Map通过<map>标签定义,<map>标签里可以使用多个<entry>作为作为子标签。每个条目包含一个键和一个值。
(6)必须在<key>标签里定义键。
(7)因为键和值的类型没有限制,所以可以自由地为它们指定<value>,<ref>,<bean>或<null>元素。
(8)可以将Map的键和值作为<entry>的属性定义:简单常量使用key和value来定义;Bean引用通过key-ref和value-ref属性定义。
1 <!-- 配置map属性值 --> 2 <bean id="newPerson" class="com.hk.beans.collections.NewPerson"> 3 <property name="name" value="xingxing"></property> 4 <property name="age" value="22"></property> 5 <property name="cars"> 6 <map> 7 <entry key="AA" value-ref="car"></entry> 8 <entry key="BB" value-ref="car2"></entry> 9 </map> 10 </property> 11 </bean>
运行结果;
1 HelloWorld's Constructor... 2 setName:Spring 3 Person [name=Mike, age=25, cars=[Car [brand=BWM, corp=ShangHai, price=100000.0, maxSpeed=300000], Car [brand=bieke, corp=<ShangHai**>, price=0.0, maxSpeed=250], Car [brand=Ford, corp=ChangAn, price=200000.0, maxSpeed=0]]] 4 NewPerson [name=xingxing, age=22, cars={AA=Car [brand=BWM, corp=ShangHai, price=100000.0, maxSpeed=300000], BB=Car [brand=bieke, corp=<ShangHai**>, price=0.0, maxSpeed=250]}]
(9)使用<props>定义java.util.Properties,该标签使用多个<prop>作为子标签。每个<prop>标签必须定义key属性。
1 <!-- 配置properties属性值 --> 2 <bean id="dataSource" class="com.hk.beans.collections.DataSource"> 3 <property name="properties"> 4 <props> 5 <prop key="user">root</prop> 6 <prop key="password">xingshengkebei</prop> 7 <prop key="jdbcUrl">jdbc:mysql://test</prop> 8 <prop key="driverClass">com.mysql.jdbc.Driver</prop> 9 </props> 10 </property> 11 </bean>
运行结果:
【6.使用utility scheme定义集合】
(1)使用集合的集合标签定义集合时,不能将集合作为独立的Bean定义,导致其他Bean无法引用该集合,所以无法在不同Bean之间共享集合。
(2)可以使用util scheme里的集合标签定义独立的集合Bean。需要注意的是,必须在<beans>根元素里添加util scheme定义。
导入util命名空间:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:util="http://www.springframework.org/schema/util" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/util 8 http://www.springframework.org/schema/util/spring-util-4.0.xsd">
配置文件中的代码:
1 <!-- 配置独立的集合bean,以供多个bean进行引用 ,需要导入util命名空间--> 2 <util:list id="cars"> 3 <ref bean="car"/> 4 <ref bean="car2"/> 5 </util:list> 6 7 <bean id="person4" class="com.hk.beans.collections.Person"> 8 <property name="name" value="Jack"></property> 9 <property name="age" value="29"></property> 10 <property name="cars" ref="cars"></property> 11 </bean>
运行结果:
1 HelloWorld's Constructor... 2 setName:Spring 3 Person [name=Jack, age=29, cars=[Car [brand=BWM, corp=ShangHai, price=100000.0, maxSpeed=300000], Car [brand=bieke, corp=<ShangHai**>, price=0.0, maxSpeed=250]]]
【7.使用p命名空间】
(1)为了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息。
(2)Spring从2.5版本开始引入一个新的p命名空间,可以通过<bean>元素属性的方式配置Bean的属性。
(3)使用p命名空间之后,基于XML的配置方式将进一步简化。
注意:要导入p命名空间:
配置文件中的代码:
1 <!-- 通过p命名空间为bean的属性空间赋值 ,需要先导入p命名空间,相对于传统的配置方式更加简洁--> 2 <bean id="person5" class="com.hk.beans.collections.Person" p:age="30" 3 p:name="China" p:cars-ref="cars"></bean>
运行结果:
1 HelloWorld's Constructor... 2 setName:Spring 3 Person [name=China, age=30, cars=[Car [brand=BWM, corp=ShangHai, price=100000.0, maxSpeed=300000], Car [brand=bieke, corp=<ShangHai**>, price=0.0, maxSpeed=250]]]
【附录】
1.怎么导入命名空间?
第一步,看左下角有个Namespaces,打开:
第二步,如图所示,按需导入即可:
有关示例的部分代码:
com.hk.beans包中:
Car.java:
1 package com.hk.beans; 2 3 public class Car { 4 private String brand; 5 private String corp; 6 private double price; 7 private int maxSpeed; 8 9 public Car(String brand, String corp, double price) { 10 super(); 11 this.brand = brand; 12 this.corp = corp; 13 this.price = price; 14 } 15 16 public void setPrice(double price) { 17 this.price = price; 18 } 19 20 public void setMaxSpeed(int maxSpeed) { 21 this.maxSpeed = maxSpeed; 22 } 23 24 @Override 25 public String toString() { 26 return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price 27 + ", maxSpeed=" + maxSpeed + "]"; 28 } 29 30 public Car(String brand, String corp, int maxSpeed) { 31 super(); 32 this.brand = brand; 33 this.corp = corp; 34 this.maxSpeed = maxSpeed; 35 } 36 }
Person.java:
1 package com.hk.beans; 2 3 public class Person { 4 private String name; 5 private int age; 6 7 private Car car; 8 9 public String getName() { 10 return name; 11 } 12 13 public void setName(String name) { 14 this.name = name; 15 } 16 17 public int getAge() { 18 return age; 19 } 20 21 public void setAge(int age) { 22 this.age = age; 23 } 24 25 public Car getCar() { 26 return car; 27 } 28 29 public void setCar(Car car) { 30 this.car = car; 31 } 32 33 @Override 34 public String toString() { 35 return "Person [name=" + name + ", age=" + age + ", car=" + car + "]"; 36 } 37 38 public Person() { 39 // TODO Auto-generated constructor stub 40 } 41 42 public Person(String name, int age, Car car) { 43 super(); 44 this.name = name; 45 this.age = age; 46 this.car = car; 47 } 48 49 }
com.hk.beans.collections包中:
NewPerson.java:
1 package com.hk.beans.collections; 2 3 import java.util.Map; 4 import com.hk.beans.Car; 5 6 public class NewPerson { 7 private String name; 8 private int age; 9 10 private Map<String,Car> cars; 11 12 public String getName() { 13 return name; 14 } 15 16 public void setName(String name) { 17 this.name = name; 18 } 19 20 public int getAge() { 21 return age; 22 } 23 24 public void setAge(int age) { 25 this.age = age; 26 } 27 28 public Map<String, Car> getCars() { 29 return cars; 30 } 31 32 public void setCars(Map<String, Car> cars) { 33 this.cars = cars; 34 } 35 36 @Override 37 public String toString() { 38 return "NewPerson [name=" + name + ", age=" + age + ", cars=" + cars 39 + "]"; 40 } 41 }
Person.java:
1 package com.hk.beans.collections; 2 3 import java.util.List; 4 import com.hk.beans.Car; 5 6 public class Person { 7 private String name; 8 private int age; 9 10 private List<Car> cars; 11 12 public String getName() { 13 return name; 14 } 15 16 public void setName(String name) { 17 this.name = name; 18 } 19 20 public int getAge() { 21 return age; 22 } 23 24 public void setAge(int age) { 25 this.age = age; 26 } 27 28 public List<Car> getCars() { 29 return cars; 30 } 31 32 public void setCars(List<Car> cars) { 33 this.cars = cars; 34 } 35 36 public Person() { 37 // TODO Auto-generated constructor stub 38 } 39 40 @Override 41 public String toString() { 42 return "Person [name=" + name + ", age=" + age + ", cars=" + cars + "]"; 43 } 44 45 public Person(String name, int age, List<Car> cars) { 46 super(); 47 this.name = name; 48 this.age = age; 49 this.cars = cars; 50 } 51 }
DataSource.java:
1 package com.hk.beans.collections; 2 3 import java.util.Properties; 4 5 public class DataSource { 6 private Properties properties; 7 8 public Properties getProperties() { 9 return properties; 10 } 11 12 public void setProperties(Properties properties) { 13 this.properties = properties; 14 } 15 16 @Override 17 public String toString() { 18 return "DataSource [properties=" + properties + "]"; 19 } 20 }