ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 4.7 Bean 定义的继承 bean 的定义可以包含很多配置信息包括构造方法参数,属性值和容器指定的信息,比 如初始化方法,静态工厂方法名称等。子 bean 定义继承从父 bean 中获得的配置元数据。 子 bean 可以覆盖一些值或者添加其它所需要的。使用父子 bean 定义可以节省很多输入。 实际上,这是一种模板形式。 如 果 你 编 程 式 地 使 用 ApplicationContext 接口,子 bean 的 定 义 可 以 由 ChildBeanDefinition 类代 表。 很多 用户 不使 用这 个级 别的 方法 ,而 是在 类似于 ClassPathXmlApplicationContext.中声明式地配置 bean 的信息。当使用基于 XML 的配置元数据时,你可以使用 parent 属性来标识一个子 bean,使用这个属性的值来标识 父 bean。 ``` <bean id="inheritedTestBean" abstract="true" class="org.springframework.beans.TestBean"> <property name="name" value="parent"/> <property name="age" value="1"/> </bean> <bean id="inheritsWithDifferentClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBean" init-method="initialize"> <property name="name" value="override"/> <!-- age属性值1将会从父bean中继承过来 --> </bean> ``` 如果没有指定一个子 bean 使用父 bean 的类,但也可以覆盖它。在这种情形中,子 bean的类必须和父 bean 兼容,也就是说,它必须接受父 bean 的属性值。 子 bean 的定义继承构造方法参数值,属性值,还有父 bean 的方法覆盖,添加新值的 选择。任何你指定的初始化方法,销毁方法,和/或 static 工厂方法设置会覆盖对应父 bean 中的设置。 剩下的设置通常是从子 bean 来定义:依赖,自动装配模式,依赖检测,单例,范围, 延迟初始化。 前面的示例明确地使用了 abstract 属性来标识了父 bean 的定义。如果父 bean 没有 指定类,那么明确地标识父 bean 就必须要有 abstract,如下所示: ``` <bean id="inheritedTestBeanWithoutClass" abstract="true"> <property name="name" value="parent"/> <property name="age" value="1"/> </bean> <bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBeanWithoutClass" init-method="initialize"> <property name="name" value="override"/> <!-- age属性值1将会从父bean中继承过来 --> </bean> ``` 父 bean 不会被实例化,因为它自己是不完整的,而且也明确地被 abstract 标记。当 bean 的定义是 abstract 这样的,那么它也仅仅被用做纯 bean 定义的模板,作为子 bean 定义的父 bean。尝试使用这种自身是 abstract 的父 bean,作为另外一个 bean 参考的属 性来指代它,或者使用父 bean 的 id 来明确使用 getBean()方法调用,会返回错误。相似 地,容器内部的 preInstantiateSingletons()方法忽略了抽象 bean 的定义。 > ![](https://box.kancloud.cn/2016-01-25_56a58526bb420.gif) > 注意 > 默认情况下,预实例化所有单例 bean。因此,如果你有仅仅想用作模板的(父)bean, 而且这个 bean 指定了一个类,那么必须将 abstract 属性设置为 true,这点是很重要的。否 则,应用上下文就会(尝试)预实例化 abstract 的 bean。