您的位置:首页 > 编程语言 > Java开发

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

2016-09-17 17:09 519 查看
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>


可正常编译。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: