abstract="true" 和 parent=""

本文介绍Spring框架中Bean定义的继承机制,包括如何通过父/子Bean定义的形式来简化配置过程,以及子Bean如何继承和覆盖父Bean的配置。

bean定义的继承

在bean定义中包含了大量的配置信息,其中包括容器相关的信息(比如初始化方法、静态工厂方法名等等)以及构造器参数和属性值。子bean定义就是从父bean定义继承配置数据的bean定义。它可以覆盖父bean的一些值,或者添加一些它需要的值。使用父/子bean定义的形式可以节省很多的输入工作。实际上,这就是一种模板形式。

当以编程的方式使用BeanFactory时,子bean定义用ChildBeanDefinition类表示。大多数用户从来不需要以这个方式使用它们,而是以类似XmlBeanFactory中的声明方式去配置bean定义。当使用基于XML的配置元数据时,给'parent'属性指定值,意味着子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"/>
  <!-- the age property value of 1 will be inherited from  parent -->

</bean>

如果子bean定义没有指定class属性,它将使用父bean定义的class属性,当然也可以覆盖它。在后面一种情况中,子bean的class属性值必须同父bean兼容,也就是说它必须接受父bean的属性值。

一个子bean定义可以从父bean继承构造器参数值、属性值以及覆盖父bean的方法,并且可以有选择地增加新的值。如果指定了init-method,destroy-method和/或静态factory-method,它们就会覆盖父bean相应的设置。

剩余的设置将总是从子bean定义处得到:依赖自动装配模式依赖检查singleton作用域延迟初始化

注意在上面的例子中,我们使用abstract属性显式地将父bean定义标记为抽象的。 下面是个父bean定义并没有指定class属性的例子,其中父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 will inherit the value of 1 from the parent bean definition-->
</bean>

由于这样的父bean是不完整的,而且还被显式标记为抽象的,因而它无法得到自己的实例。抽象bean定义可作为子bean定义的模板。若要尝试单独使用这样的父bean(比如将它作为其他bean的ref属性而引用,或者直接使用这个父bean的id作为参数调用getBean()方法),将会导致错误。同样地,容器内部的preInstantiateSingletons()方法会完全忽略abstract的bean定义。

注意

默认情况下,ApplicationContext不是BeanFactory)会预实例化所有singleton的bean。因此很重要的一点是:如果你只想把一个(父)bean定义当作模板使用,而它又指定了class属性,那么你就得将'abstract'属性设置为'true',否则应用上下文将会(试着)预实例化抽象bean。


原文地址:http://blog.163.com/yangyanninhao@126/blog/static/239900292007101863043493/

很不错。受教了。

帮我写几个方法,我使用的是mybatis-plus。@Data @Component public class DictUtil { @Autowired private DictionaryDataService dictionaryDataService; // 通过输入字典名称来获取字典对象,返回的是list。查询也使用list方式查询,但是是eq查询,没有返回空list // 通过输入字典id来获取字典对象,返回的是对象。没有返回null // 通过输入字典id来获取对应类别主键(f_dictionary_type_id)下全部字典对象,返回list // 通过字典id列表获取对应的字典对象列表的map集合,k是字典id,v是字典对象返回map,如果id对应的对象没查询到,则value设置为null。 } /** * 字典数据 * * @author JNPF开发平台组 * @version V3.1.0 * @copyright 引迈信息技术有限公司(https://www.jnpfsoft.com) * @date 2019年9月27日 上午9:18 */ @Data @TableName("base_dictionary_data") public class DictionaryDataEntity extends SuperExtendEntity.SuperExtendDEEntity<String> implements Serializable { /** * 上级 */ @TableField("f_parent_id") private String parentId; /** * 名称 */ @TableField("f_full_name") private String fullName; /** * 编码 */ @TableField("f_en_code") private String enCode; /** * 拼音 */ @TableField("f_simple_spelling") private String simpleSpelling; /** * 默认 */ @TableField("f_is_default") private Integer isDefault; /** * 类别主键 */ @TableField("f_dictionary_type_id") private String dictionaryTypeId; } @Data @ToString(callSuper = true) @EqualsAndHashCode public abstract class SuperBaseEntity implements Serializable { @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperIBaseEntity<T> extends SuperBaseEntity { /** * 主键 */ @TableId(TableFieldsNameConst.F_ID) public T id; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperTBaseEntity<T> extends SuperIBaseEntity<T> { /** * 租户id */ @TableField(value = TableFieldsNameConst.F_TENANT_ID , fill = FieldFill.INSERT_UPDATE) private String tenantId; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperCBaseEntity<T> extends SuperTBaseEntity<T> { /** * 创建时间 */ @TableField(value = TableFieldsNameConst.F_CREATOR_TIME , fill = FieldFill.INSERT) private Date creatorTime; /** * 创建用户 */ @TableField(value = TableFieldsNameConst.F_CREATOR_USER_ID , fill = FieldFill.INSERT) private String creatorUserId; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperCUBaseEntity<T> extends SuperCBaseEntity<T> { /** * 修改时间 */ @TableField(value = TableFieldsNameConst.F_LAST_MODIFY_TIME , fill = FieldFill.UPDATE) private Date lastModifyTime; /** * 修改用户 */ @TableField(value = TableFieldsNameConst.F_LAST_MODIFY_USER_ID , fill = FieldFill.UPDATE) private String lastModifyUserId; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperCUDBaseEntity<T> extends SuperCUBaseEntity<T> { /** * 删除标志 */ @TableField(value = TableFieldsNameConst.F_DELETE_MARK , updateStrategy = FieldStrategy.IGNORED) private Integer deleteMark; /** * 删除时间 */ @TableField(value = TableFieldsNameConst.F_DELETE_TIME , fill = FieldFill.UPDATE) private Date deleteTime; /** * 删除用户 */ @TableField(value = TableFieldsNameConst.F_DELETE_USER_ID , fill = FieldFill.UPDATE) private String deleteUserId; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperCDBaseEntity<T> extends SuperCBaseEntity<T> { /** * 删除标志 */ @TableField(value = TableFieldsNameConst.F_DELETE_MARK , updateStrategy = FieldStrategy.IGNORED) private Integer deleteMark; /** * 删除时间 */ @TableField(value = TableFieldsNameConst.F_DELETE_TIME , fill = FieldFill.UPDATE) private Date deleteTime; /** * 删除用户 */ @TableField(value = TableFieldsNameConst.F_DELETE_USER_ID , fill = FieldFill.UPDATE) private String deleteUserId; } } @Data @ToString(callSuper = true) @EqualsAndHashCode public abstract class SuperEntity<T> extends SuperBaseEntity.SuperCUDBaseEntity<T> { } @Data @ToString(callSuper = true) @EqualsAndHashCode public abstract class SuperExtendEntity<T> extends SuperEntity<T>{ /** * 排序码 */ @TableField(TableFieldsNameConst.F_SORT_CODE) private Long sortCode; @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperExtendDescriptionEntity<T> extends SuperExtendEntity<T> { /** * 描述 */ @TableField(TableFieldsNameConst.F_DESCRIPTION) private String description; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperExtendEnabledEntity<T> extends SuperExtendEntity<T> { /** * 有效标志 (0-默认,禁用,1-启用) */ @TableField(value =TableFieldsNameConst.F_ENABLED_MARK,fill = FieldFill.INSERT) private Integer enabledMark; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperExtendDEEntity<T> extends SuperExtendEntity<T> { /** * 描述 */ @TableField(TableFieldsNameConst.F_DESCRIPTION) private String description; /** * 有效标志 (0-默认,禁用,1-启用) */ @TableField(value =TableFieldsNameConst.F_ENABLED_MARK,fill = FieldFill.INSERT) private Integer enabledMark; } } @Data @ToString(callSuper = true) @EqualsAndHashCode public abstract class SuperExtendEntity<T> extends SuperEntity<T>{ /** * 排序码 */ @TableField(TableFieldsNameConst.F_SORT_CODE) private Long sortCode; @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperExtendDescriptionEntity<T> extends SuperExtendEntity<T> { /** * 描述 */ @TableField(TableFieldsNameConst.F_DESCRIPTION) private String description; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperExtendEnabledEntity<T> extends SuperExtendEntity<T> { /** * 有效标志 (0-默认,禁用,1-启用) */ @TableField(value =TableFieldsNameConst.F_ENABLED_MARK,fill = FieldFill.INSERT) private Integer enabledMark; } @Data @ToString(callSuper = true) @EqualsAndHashCode public static abstract class SuperExtendDEEntity<T> extends SuperExtendEntity<T> { /** * 描述 */ @TableField(TableFieldsNameConst.F_DESCRIPTION) private String description; /** * 有效标志 (0-默认,禁用,1-启用) */ @TableField(value =TableFieldsNameConst.F_ENABLED_MARK,fill = FieldFill.INSERT) private Integer enabledMark; } }
最新发布
12-12
对于下面布局,由于recycleview被包含在NestedScrollView中,导致加载页面时会把recycleview的onCreatedViewHolder多次执行,由于这个页面中有一个textview需要一起滚动,所以能不能使用headerview优化一下,使用kotlin语言。 布局如下: <androidx.core.widget.NestedScrollView android:id="@+id/trusted_devices_nv" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/toolbar"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <com.tplink.design.card.TPConstraintCardView android:id="@+id/trusted_devices_card" style="?attr/materialCardViewStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/tpds_card_view_spacing" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/trusted_devices_rv" android:layout_width="match_parent" android:layout_height="wrap_content" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:nestedScrollingEnabled="false"/> </com.tplink.design.card.TPConstraintCardView> <TextView android:id="@+id/trusted_devices_tv" style="@style/Widget.TPDesign.TextView.Secondary.Body1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/tpds_card_view_margin_horizontal" android:layout_marginTop="@dimen/tpds_all_dp_10" android:layout_marginBottom="@dimen/tpds_card_view_spacing" android:text="@string/mp_ac_mfa_trusted_devices_description" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/trusted_devices_card" app:layout_constraintVertical_bias="0" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.core.widget.NestedScrollView>
09-29
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值