XML配置里的Bean自动装配
Spring IOC容器可以自动装配Bean,需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式,模式包含:byType,byName,constructor
举例:
常规用法:
Member.java
package com.dx.spring.bean.autowire;public class Member { private String name; private int age; private Address address; private Work work; 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 Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Work getWork() { return work; } public void setWork(Work work) { this.work = work; } @Override public String toString() { return "Member [name=" + name + ", age=" + age + ", address=" + address + ", work=" + work + "]"; }}
Address.java
package com.dx.spring.bean.autowire;public class Address { private String city; private String area; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getArea() { return area; } public void setArea(String area) { this.area = area; } @Override public String toString() { return "Address [city=" + city + ", area=" + area + "]"; }}
Work.java
package com.dx.spring.bean.autowire;public class Work { private String company; private int money; public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } @Override public String toString() { return "Work [company=" + company + ", money=" + money + "]"; }}
bean-autowire.xml
Main.java
package com.dx.spring.bean.autowire;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main { public static void main(String[] args) { ApplicationContext cxt = new ClassPathXmlApplicationContext("bean-autowire.xml"); Member member = (Member) cxt.getBean("member"); System.out.println(member); }}
测试打印结果:
Member [name=Rose, age=27, address=Address [city=beijing, area=huilongguan], work=Work [company=baidu, money=80000]]
1)byName(根据名称自动装配):
必须将目标Bean的名称和属性名设置的完成相同。
修改常规用法中的bean-autowire.xml:
此时,如果修改work bean的名字为work2
则Main.java调用时,无法匹配上work属性:
Member [name=Rose, age=27, address=Address [city=beijing, area=huilongguan], work=null]
2)byType(根据类型自动装配):
若IOC容器中有多个与目标Bean类型一致的Bean,在这种情况下,Spring将无法判定哪个Bean最合适该属性,所以不能执行自动装配。
此时如果在bean-autowire.xml中包含多个Work的bean时:
此时运行时,将会抛出异常:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'member' defined in class path resource [bean-autowire.xml]: Unsatisfied dependency expressed through bean property 'work'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.dx.spring.bean.autowire.Work' available: expected single matching bean but found 2: work,work3
3)constructor(通过构造器自动装配):
当Bean中存在多个构造器时,此种自动装配方式将会很复杂,不推荐使用。
XML配置里的Bean自动装配缺点
1)在bean配置文件里设置autowire属性进行自动装配将会装配bean所有属性。然而,若只希望装配个别属性是,autowire属性就不够灵活了。
2)autowire属性要么根据类型自动装配,要么根据名称自动装配,不能两者兼而有之。
3)一般情况下,在实际项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力。
bean之间的关系:继承;依赖。
bean之间的关系:继承
1)Spring允许继承bean的配置,被集成的bean称为父bean。继承这个父bean的bean称为子bean。
2)子bean从父bean中继承配置,包括bean的属性配置
3)父bean可以作为配置模版,也可以作为bean实例。若只想把父bean作为模版,可以设置<bean>的abstract属性为true,这样Spring将不会实例化这个bean。
4)并不是<bean>元素里的所有属性都会被继承。比如:autowire,abstract等。
5)也可以忽略父bean的class属性,让子bean指定自己的类,而共享相同的属性配置,但此时abstract必须设为true。
常规示例:有两个address bean,此时用法如下:
bean-relation-dependence.xml
Adress.java
package com.dx.spring.beans.relation_dependence;public class Address { private String city; private String street; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } @Override public String toString() { return "Address [city=" + city + ", street=" + street + "]"; }}
Client.java
package com.dx.spring.beans.relation_dependence;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Client { public static void main(String[] args) { ApplicationContext cxt = new ClassPathXmlApplicationContext("bean-relation-dependence.xml"); Address address = (Address) cxt.getBean("address"); System.out.println(address); Address address2 = (Address) cxt.getBean("address2"); System.out.println(address2); }}
a)实际上address2是可以通过继承address bean的,修改bean-relation-dependence.xml为如下:
b)可以把父类bean配置为一个模版(抽象)bean:
此时address这个bean是不能够被实例化的,否则会抛出异常。
package com.dx.spring.beans.relation_dependence;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Client { public static void main(String[] args) { ApplicationContext cxt = new ClassPathXmlApplicationContext("bean-relation-dependence.xml"); // 当把address bean的属性设置abstract="true"时,该bean不能被实例化,否则会抛出异常。 // Address address = (Address) cxt.getBean("address"); // System.out.println(address); Address address2 = (Address) cxt.getBean("address2"); System.out.println(address2); }}
c)也可以把父类bean配置为一个无class属性的模版(抽象)bean:
备注:如果一个bean的class属性没有被指定,则该bean必须为一个抽象bean。
bean之间的关系:依赖
1)spring允许用户通过depends-on属性设定bean前置依赖的bean,前置依赖的bean会在本bean实例化之前创建好。
2)如果前置依赖于多个bean,则可以通过逗号、空格的方式配置bean的名称
bean-relation-dependence.xml
此时,如果depends-on的car不存在,则会抛出异常。