7.8 深入理解容器中的Bean
Spring框架绝大部分工作都集中在对容器中Bean的管理上,包括管理容器中Bean的生命周期、使用Bean继承等特殊功能。通过深入的管理,应用程序可以更好地使用这些Java组件(容器中的Bean对应用而言,往往是一个组件)。
7.8.1 抽象Bean与子Bean
在实际开发中,可能出现的场景是:随着项目越来越大, Spring配置文件中出现了多个<bean>配置具有大致相同的配置信息,只有少量信息不同,这将导致配置文件出现很多重复的内容。如果保留这种配置,则可能导致的问题是:
- 配置文件臃肿。
- 后期难以修改、维护。
为了解决上面问题,可以考虑把多个<bean>配置中相同的信息提取出来,集中成配置模板——这个配置模板并不是真正的Bean,因此Spring不应该创建该配置模板,于是需要为该<bean>配置增加abstract="true"属性,这就是抽象Bean。
抽象Bean不能被实例化, Spring容器不会创建抽象Bean实例。抽象Bean的价值在于被继承,抽象Bean通常作为父Bean让子Bean继承。
抽象Bean只是配置信息的模板,指定abstract="true"属性即可阻止Spring实例化该Bean,因此抽象Bean可以不指定class属性。
抽象Bean不能实例化
抽象Bean不能实例化,因此既不能通过getBean()显式地获得抽象Bean实例,也不能将抽象Bean注入成其他Bean依赖。不管怎样,只要程序企图实例化抽象Bean,都将导致错误.
父Bean中可以继承的配置信息
将大部分相同信息配置成抽象Bean之后,将实际的Bean实例配置成该抽象Bean的子Bean即可。子Bean定义可以从父Bean继承实现类、构造器参数、属性值等配置信息,除此之外,子Bean配置可以增加新的配置信息,并可指定新的配置信息覆盖父Bean的定义。
子bean元素通过parent属性指定其父bean
通过为一个<bean>元素指定parent属性即可指定该Bean的父Bean, parent属性指定该Bean所继承的父Bean的id.
父Bean中无法被继承的属性
子Bean无法从父Bean继承如下属性:depends-on、 autowire、 singleton、 scope、lazy-init,这些属性将总是从子Bean定义中获得,或采用默认值
修改上面的配置文件如下,增加了子Bean定义。
1 |
|
在配置文件中chinese和american Bean都指定了parent="personTemplate"属性,这表明这两个Bean都可从父Bean那里继承得到配置信息,虽然这两个Bean都没有直接指定<property>子元素,但它们会从personTemplate模板那里继承得到两个<property>子元素。也就是说,上面的配置信息实际上相当于如下配置:
1 | <bean id="chinese" class="org.crazyit.app.service.impl.Chinese"> |
使用抽象Bean的好处
不使用抽象Bean的配置方式不仅会导致配置文件臃肿,而且不利于项目后期的修改、维护,如果有一天项目需要改变chinese、 american的name或所依赖的Axe对象,程序需要逐个修改每个Bean的配置信息。
如果使用了抽象Bean,则只需要修改Bean模板的配置即可,所有继承该Bean模板的子Bean的配置信息都会随之改变。
子类会覆盖父类继承来的相同的配置信息
如果父Bean(抽象Bean)指定了class属性,那么子Bean连class属性都可省略,子Bean将用与父Bean相同的实现类。除此之外,子Bean也可覆盖父Bean的配置信息:当子Bean拥有和父Bean相同的配置信息时,将使用以子Bean的配置信息。
项目结构
1 | E:\workspace_QingLiangJiJavaEEQiYeYingYongShiZhang5\abstract |