Spring学习第六天:Bean之间的关系

Bean之间的关系有两种:继承和依赖

继承
Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean
子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置
子 Bean 也可以覆盖从父 Bean 继承过来的配置
父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置 的abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean
并不是 元素里的所有属性都会被继承. 比如: autowire, abstract 等.
也可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true

新建一个bean-relation.xml配置文件
XML配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="address" class="com.atguigu.spring.beans.autowire.Address"
    p:city="BeiJing" p:street="WuDaoKou"></bean>
<bean id="address2" class="com.atguigu.spring.beans.autowire.Address"
    p:city="BeiJing" p:street="DaZhongsi"></bean>
</beans>

调用该Bean

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-relation.xml");
Address address = (Address) ctx.getBean("address");
System.out.println(address);
Address address2 = (Address) ctx.getBean("address2");
System.out.println(address2);

输出结果:

Address [city=BeiJing, street=WuDaoKou]
Address [city=BeiJing, street=DaZhongsi]

我们可以看到,address和address2的配置其实很相似,并且city的值是相同的

此时我们可以使用parent属性来简化XML配置
XML配置如下

<bean id="address" class="com.atguigu.spring.beans.autowire.Address"
    p:city="BeiJing" p:street="WuDaoKou"></bean>
<!-- bean 配置的继承,使用bean 的parent 属性指定继承那个bean的配置 -->
<bean id="address2" p:street="DaZhongsi" parent="address"></bean>

输出结果

Address [city=BeiJing, street=WuDaoKou]
Address [city=BeiJing, street=DaZhongsi]

将Bean作为一个模板,可以使用abstract=”true”,这是一个抽象bean,抽象bean不能被实例化,就是用来被继承的

XML配置如下

<!-- 抽象bean: bean的abstract属性为true的bean,这样的bean不能被IOC容器实例化,只用来被继承配置-->
<bean id="address" class="com.atguigu.spring.beans.autowire.Address"
    p:city="BeiJing" p:street="WuDaoKou" abstract="true"></bean>
<bean id="address2" p:street="DaZhongsi" parent="address"></bean>

调用bean

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-relation.xml");
Address address = (Address) ctx.getBean("address");
System.out.println(address);
Address address2 = (Address) ctx.getBean("address2");
System.out.println(address2);

遇到如下Error

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:1273)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:283)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.j

可见,abstract=”true”修饰的bean无法被实例化
address这个bean就是用来被继承的

若某一个bean的class属性没有指定,则该bean必须是一个抽象bean
XML配置如下

<bean id="address"
    p:city="BeiJing" p:street="WuDaoKou"></bean>
<bean id="address2" p:street="DaZhongsi" parent="address"></bean>

编译时遇到如下error

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'address' defined in class path resource [beans-relation.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:1076)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1021)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.atguigu.spring.beans.relation.Main.main(Main.java:11)
Caused by: java.lang.IllegalStateException: No bean class specified on bean definition
    at org.springframework.beans.factory.support.AbstractBeanDefinition.getBeanClass(AbstractBeanDefinition.java:354)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:66)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1069)
    ... 13 more

所以我们必须将address设置为抽象bean

<bean id="address" p:city="BeiJing" p:street="WuDaoKou" abstract="true"></bean>
<bean id="address2" class="com.atguigu.spring.beans.autowire.Address" p:street="DaZhongsi" parent="address"></bean>

输出结果:

Address [city=BeiJing, street=DaZhongsi]

Note:在继承的时候,abstract并没有被继承,否则address2也无法被实例化

并且,bean之间可以继承多层
XML如下:

<bean id="address" p:city="BeiJing" p:street="WuDaoKou" abstract="true"></bean>
<bean id="address2" class="com.atguigu.spring.beans.autowire.Address" parent="address"></bean>
<bean id="address3" class="com.atguigu.spring.beans.autowire.Address" p:street="DaChongsi" parent="address2"></bean>

输出结果:

Address [city=BeiJing, street=WuDaoKou]
Address [city=BeiJing, street=DaChongsi]

Bean之间的依赖关系
Spring 允许用户通过 depends-on 属性设定 Bean 前置依赖的Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好
如果前置依赖于多个 Bean,则可以通过逗号,空格或的方式配置 Bean 的名称

现我们配置一个Person的bean,要求必须有一个关联的car,换句话说,person这个bean依赖于Car 这个bean

XML配置如下:

<bean id="person" class="com.atguigu.spring.beans.autowire.Person" p:name="Tom" p:address-ref="address2" depends-on="car"></bean>

运行时出错

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'car' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:638)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1159)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:282)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.atguigu.spring.beans.relation.Main.main(Main.java:12)

需要配置car

<bean id="car" class="com.atguigu.spring.beans.autowire.Car" p:brand="Audi" p:price="300000"></bean>

可正常编译。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值