Spring学习--Bean 之间的关系

Posted Chinda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring学习--Bean 之间的关系相关的知识,希望对你有一定的参考价值。

Bean 之间的关系:继承、依赖。

Bean 继承:

  • Spring 允许继承 bean 的配置 , 被继承的 bean 称为父 bean , 继承这个父 bean 的 bean 称为子 bean。
  • 子 bean 从父 bean 中继承配置 , 包括 bean 的属性配置。
  • 子 bean 也可以覆盖从父 bean 继承过来的配置。
  • 父 bean 可以作为配置模板 , 也可以作为 bean 实例。若只想把父 bean 作为模板 , 可以设置 <bean> 的 abstract 属性为 true , 这样 IOC容器将不会实例这个 bean。
  • 并不是 <bean> 元素里的所有属性都会被继承。比如: autowire , abstract 等。
  • 父 bean 的 class 属性可以忽略 , 让子 bean 指定自己的类 , 而共享相同的属性配置。但此时 abstract 必须设为 true。
 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:p="http://www.springframework.org/schema/p"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 6 
 7     <bean id="address" class="com.itdoc.spring.extendsinfo.Address" p:city="DaLian" p:street="ShaHeKou"/>
 8 
 9     <bean id="address1" class="com.itdoc.spring.extendsinfo.Address" p:street="GanJingZi" parent="address"/>
10 
11 </beans>
 1 package com.itdoc.spring.extendsinfo;
 2 
 3 /**
 4  * http://www.cnblogs.com/goodcheap
 5  *
 6  * @author: Wáng Chéng Dá
 7  * @create: 2017-03-01 20:48
 8  */
 9 public class Address {
10 
11     private String city;
12 
13     private String street;
14 
15     public String getCity() {
16         return city;
17     }
18 
19     public void setCity(String city) {
20         this.city = city;
21     }
22 
23     public String getStreet() {
24         return street;
25     }
26 
27     public void setStreet(String street) {
28         this.street = street;
29     }
30 
31     @Override
32     public String toString() {
33         return "Address{" +
34                 "city=\'" + city + \'\\\'\' +
35                 ", street=\'" + street + \'\\\'\' +
36                 \'}\';
37     }
38 }
 1 package com.itdoc.spring.extendsinfo;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 /**
 7  * http://www.cnblogs.com/goodcheap
 8  *
 9  * @author: Wáng Chéng Dá
10  * @create: 2017-03-01 20:55
11  */
12 public class Main {
13 
14     public static void main(String[] args) {
15         ApplicationContext app = new ClassPathXmlApplicationContext("beans_extends.xml");
16         Address address = (Address) app.getBean("address");
17         System.out.println(address);
18 
19         System.out.println("-------------------");
20         address = (Address) app.getBean("address1");
21         System.out.println(address);
22         
23     }
24 }

 

控制台输出:

Address{city=\'DaLian\', street=\'ShaHeKou\'}
-------------------
Address{city=\'DaLian\', street=\'GanJingZi\'}

 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:p="http://www.springframework.org/schema/p"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 6 
 7     <bean id="address" class="com.itdoc.spring.extendsinfo.Address" p:city="DaLian" p:street="ShaHeKou" abstract="true"/>
 8 
 9     <bean id="address1" class="com.itdoc.spring.extendsinfo.Address" p:street="GanJingZi" parent="address"/>
10 
11 </beans>

 

控制台输出:

Exception in thread "main" org.springframework.beans.factory.BeanIsAbstractException: Error creating bean with name \'address\': Bean definition is abstract
at org.springframework.beans.factory.support.AbstractBeanFactory.checkMergedBeanDefinition(AbstractBeanFactory.java:1321)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:285)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
at com.itdoc.spring.extendsinfo.Main.main(Main.java:16)

原因:address 成为了模板 bean , 不可以实例化。

 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:p="http://www.springframework.org/schema/p"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 6 
 7     <bean id="address" p:city="DaLian" p:street="ShaHeKou"/>
 8 
 9     <bean id="address1" class="com.itdoc.spring.extendsinfo.Address" p:street="GanJingZi" parent="address"/>
10 
11 </beans>
 1 package com.itdoc.spring.extendsinfo;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 /**
 7  * http://www.cnblogs.com/goodcheap
 8  *
 9  * @author: Wáng Chéng Dá
10  * @create: 2017-03-01 20:55
11  */
12 public class Main {
13 
14     public static void main(String[] args) {
15         ApplicationContext app = new ClassPathXmlApplicationContext("beans_extends.xml");
16         Address address = (Address) app.getBean("address1");
17         System.out.println(address);
18 
19     }
20 }

 

控制台输出:

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name \'address\' defined in class path resource [beans_extends.xml]: Instantiation of bean failed; nested exception is java.lang.IllegalStateException: No bean class specified on bean definition
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name \'address\' defined in class path resource [beans_extends.xml]: Instantiation of bean failed; nested exception is java.lang.IllegalStateException: No bean class specified on bean definition
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1155)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.itdoc.spring.extendsinfo.Main.main(Main.java:15)
Caused by: java.lang.IllegalStateException: No bean class specified on bean definition
at org.springframework.beans.factory.support.AbstractBeanDefinition.getBeanClass(AbstractBeanDefinition.java:372)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:66)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
... 13 more

原因:父 bean 中的 class 属性忽略 , 该 bean 必须是 abstract="true" 的。

 

Bean 依赖:

  • Spring 允许用户通过 depends-on 属性设定 bean 前置依赖的 bean , 前置依赖的 bean 会在本 bean 实例化前创建好。
  • 如果前置依赖于多个 bean , 则可以通过逗号或空格的方式配置 bean 的名称。
 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:p="http://www.springframework.org/schema/p"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 6 
 7     <bean id="person" class="com.itdoc.spring.extendsinfo.Person" p:name="华崽儿" p:car-ref="car" p:address-ref="address"/>
 8     <bean id="address" class="com.itdoc.spring.extendsinfo.Address" p:city="DaLian" p:street="ShaHeKou"/>
 9     <bean id="car" class="com.itdoc.spring.beans.Car" p:brand="8手奥拓" p:price="3000" p:maxSpeed="120"/>
10 
11 </beans>
 1 package com.itdoc.spring.extendsinfo;
 2 
 3 import com.itdoc.spring.beans.Car;
 4 
 5 /**
 6  * http://www.cnblogs.com/goodcheap
 7  *
 8  * @author: Wáng Chéng Dá
 9  * @create: 2017-03-01 20:47
10  */
11 public class Person {
12 
13     private String name;
14 
15     private Address address;
16 
17     private Car car;
18 
19     public String getName() {
20         return name;
21     }
22 
23     public void setName(String name) {
24         this.name = name;
25     }
26 
27     public Address getAddress() {
28         return address;
29     }
30 
31     public void setAddress(Address address) {
32         this.address = address;
33     }
34 
35     public Car getCar() {
36         return car;
37     }
38 
39     public void setCar(Car car) {
40         this.car = car;
41     }
42 
43     public Person() {
44         System.out.println("I am Person Constructor...");
45     }
46 
47     @Override
48     public String toString() {
49         return "Person{" +
50                 "name=\'" + name + \'\\\'\' +
51                 ", address=" + address +
52                 ", car=" + car +
53                 \'}\';
54     }
55 }
 1 package com.itdoc.spring.extendsinfo;
 2 
 3 /**
 4  * http://www.cnblogs.com/goodcheap
 5  *
 6  * @author: Wáng Chéng Dá
 7  * @create: 2017-03-01 20:48
 8  */
 9 public class Address {
10 
11     private String city;
12 
13     private String street;
14 
15     public String getCity() {
16         return city;
17     }
18 
19     public void setCity(String city) {
20         this.city = city;
21     }
22 
23     public String getStreet() {
24         return street;
25     }
26 
27     public void setStreet(String street) {
28         this.street = street;
29     }
30 
31     public Address() {
32         System.out.println("I am Address Constructor...");
33     }
34 
35     @Override
36     public String toString() {
37         return "Address{" +
38                 "city=\'" + city + \'\\\'\' +
39                 ", street=\'" + street + \'\\\'\' +
40                 \'}\';
41     }
42 }
 1 package com.itdoc.spring.beans;
 2 
 3 /**
 4  * 集合中的对象
 5  * http://www.cnblogs.com/goodcheap
 6  *
 7  * @author: Wáng Chéng Dá
 8  * @create: 2017-02-28 19:56
 9  */
10 public class Car {
11 
12     private String brand;
13 
14     private double price;
15 
16     private int maxSpeed;
17 
18     public String getBrand() {
19         return brand;
20     }
21 
22     public void setBrand(String brand) {
23         this.brand = brand;
24     }
25 
26     public double getPrice() {
27         return price;
28     }
29 
30     public void setPrice(double price) {
31         this.price = price;
32     }
33 
34     public int getMaxSpeed() {
35         return maxSpeed;
36     }
37 
38     public void setMaxSpeed(int maxSpeed) {
39         this.maxSpeed = maxSpeed;
40     }
41 
42     public Car() {
43         System.out.println("I am Car Constructor...");
44     }
45 
46     @Override
47     public String toString() {
48         return "Car{" +
49                 "brand=\'" + brand + \'\\\'\' +
50                 ", price=" + price +
51                 ", maxSpeed=" + maxSpeed +
52                 \'}\';
53     }
54 }
 1 package com.itdoc.spring.extendsinfo;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 /**
 7  * http://www.cnblogs.com/goodcheap
 8  *
 9  * @author: Wáng Chéng Dá
10  * @create: 2017-03-01 20:55
11  */
12 public class Main {
13 
14     public static void main(String[] args) {
15         ApplicationContext app = new ClassPathXmlApplicationContext("beans_extends.xml");
16         Person person = (Person) app.getBean("person");
17         System.out.println(person);
18 
19     }
20 }

 

控制台输出:

I am Person Constructor...
I am Address Constructor...
I am Car Constructor...
Person{name=\'华崽儿\', address=Address{city=\'DaLian\', street=\'ShaHeKou\'}, car=Car{brand=\'8手奥拓\', price=3000.0, maxSpeed=120}}

 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:p="http://www.springframework.org/schema/p"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 6 
 7     <bean id="person" class="com.itdoc.spring.extendsinfo.Person" p:name="华崽儿" p:car-ref="car" p:address-ref="address" depends-on="car, address"/>
 8 
 9     <bean id="address" class="com.itdoc.spring.extendsinfo.Address" p:city="DaLian" p:street="ShaHeKou"/>
10 
11     <bean id="car" class="com.itdoc.spring.beans.Car" p:brand="8手奥拓" p:price="3000" p:maxSpeed="120"/>
12 
13 </beans>

 

控制台输出:

I am Car Constructor...
I am Address Constructor...
I am Person Constructor...
Person{name=\'华崽儿\', address=Address{city=\'DaLian\', street=\'ShaHeKou\'}, car=Car{brand=\'8手奥拓\', price=3000.0, maxSpeed=120}}

根据控制台输出我们不难看出 bean 的初始化顺序发生了改变 , 前置依赖的 bean 会在本 bean 实例化前创建好。

 

以上是关于Spring学习--Bean 之间的关系的主要内容,如果未能解决你的问题,请参考以下文章

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段

Spring 学习笔记—— Bean之间的关系作用域自动装配

spring bean之间的关系:继承,依赖,依赖注入

hsp Spring学习笔记

Spring入门IOC和AOP学习笔记

Spring学习笔记—装配Bean