`
langgufu
  • 浏览: 2306916 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring 抽象bean及继承(模板)

 
阅读更多

我们在应用Spring时,在一般的设计时,肯定要用的抽象类。那在Spring中怎么样配置这些抽象Bean呢。请看下面:

如果两个bean 之间的配置信息非常相似,可利用继承来减少重复配置工作。
继承是指子bean 定义可从父bean 定义继承部分配置信息,也可覆盖特定的配置信
息,或者添加一些配置。使用继承配置可以节省很多的配置工作。在实际应用中,通用
配置会被配置成模板,可供子bean 继承。

使用abstract 属性

正如前面所介绍的,通用的配置会被配置成模板,而模板不需要实例化,仅仅作为子bean 定义的模板使用。而ApplicationContext 默认预初始化所有的singleton bean 。使用abstract 属性,可以阻止模板bean 被预初始化。
abstract 属性为true 的bean 称为抽象bean ,容器会忽略所有的抽象bean 定义,预初始化时不初始化抽象bean。
如果没有定义abstract 属性,该属性默认为false 。如下配置文件定义了一个抽象bean ,该抽象bean 作为模板使用:

public class SteelAxe implements Axe
{

//count 是个状态值,每次执行chop 方法该值增加1
private int count = 0;
public SteelAxe(){
System.out.println("Spring实例化依赖bean: SteelAxe 实例.. .");
}
//测试用方法
public String chop(){
return "钢斧砍柴真快" + ++count;
}

}

public class Chinese implements Person

//面向Axe 接口编程,而不是具体的实现类
private Axe axe;
//默认的构造器
public Chinese(){
System.out.println("Spring实例化主调bean: Chinese 实例... ");
}
//设值注入所需的setter 方法
public void setAxe( Axe axe){
System.out.pr工ntln (" Spring 执行依赖关系注入...");
this.axe = axe;
}
//实现Person 接口的useAxe 方法
public void useAxe(){
System.out.println(axe.chop());
}

}

<?xml version="1.0" encoding="gb2312"?>
<!一指定Spring 配置文件的dtd>
<lDOCTYPE beans PUBL工C "-//SPRING//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<!一Spring 配置文件的根元素一〉
<beans>
<bean id="steelAxe" class="lee.SteelAxe"/>
<!… 通过abstract 属性定义该bean 是抽象bean-->
<bean id="chineseTemplate" class="lee.Chinese" abstract="true">
<!一定义依赖注入的属性一〉
<property name="axe">
<ref local="steelAxe"/>
</property>
</bean>
</beans>
从配置文件中可以看出,抽象bean 的定义与普通bean 的定义几乎没有区别,仅仅增加abstract 属性为true ,
但主程序执行结果却有显著的差别。下面的主程序采用AppliactionContext 作为Spring 容器,
. AppliationContext 默认预初始化所有的singleton bean。其主程序部分如下:

public class BeanTest
{

public static void main(String[] args)throws Exception{
ApplicationContext ctx = new FileSysternXmlApplicationContext("bean.xml");
}

}
//主程序部分仅仅实例化了ApplicationContext,在实例化ApplicationContext时,默认实例化singleton bean。
程序执行结果如下:

Spring 实例化依赖bean: SteelAxe 实例.. .

容器并没有实例化chineseTemplate bean ,而忽略了所有声明为abstract 的beano 如果取消abstract 属性定义,
则程序执行结果如下:

Spring 实例化依赖bean: SteelAxe 实~J...
Spring 实例化主调bean: Chinese 实例.. .
Spring 执行依赖关系注入...


可以看出,抽象bean 是一个bean 模板,容器会忽略抽象bean 定义,因而不会实例化抽象bean。
但抽象bean 无须实例化,因此可以没有class 属性。如下的配置文件也有效:
<?xml version="1.0" e口coding="gb2312"?>
<!一指定Spring 配置文件的dtd>
<!DOCTYPE beans PUBLIC "-/!SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd''>
<! -- Spring 配置文件的根元素-->
<beans>
<bean id="steelAxe" class="lee.SteelAxe"/>
<!一通过abstract 属性定义该bean 是抽象bean,抽象bean 没有指定class 属性一〉
<bean id="chineseTemplate" abstract="true">
<!… 定义依赖注入的属性一〉
<property name="axe">
<ref local="steelAxe"/>
</property>
</bean〉
</beans>

注意:抽象bean 不能实例化,既不能通过getBean 获得抽象bean,也不能让其他bean 
的ref 属性值指向抽象bean,因而只要企图实例化抽象bean,都将导致错误


定义子bean

我们把指定了parent 属性值的bean 称为子bean; parent 指向子bean 的模板,称为父bean 。
子bean 可以从父bean 继承实现类、构造器参数及属性值,也可以增加新的值。如果指定了init-method , 
destroy-method 和factory-method 的属性,则它们会覆盖父bean的定义。子bean 无法从父bean 
继承如下属性: depends-on, autowire, dependency-check,singleton, lazy-init。这些属性将从子bean 定义中获得,
或采用默认值。通过设置parent 属性来定义子bean , parent 属性值为父bean id。修改上面的配置文
件如下,增加了子bean 定义:
<?xml version="1.0" encoding="gb2312"?>
<!一指定Spring 配置文件的dtd>
<lDOCTYPE beans PUBL工C "-//SPRING//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<!-- Spring 配置文件的根元素一〉
<beans>
<bean id="steelAxe" class="lee.SteelAxe"/>
<!一通过abstract 属性定义该bean 是抽象bean-->
<bean id="chineseTemplate" class="lee.Chinese" abstract="true">
<!-- 定义依赖注入的属性一〉
<property name="axe">
<ref local="steelAxe"/>
</property>
</bean>
<!一通过parent 属性定义子bean ?
<bean id="chinese" parent="chineseTemplate"/>
</beans>
子bean 与普通bean 的定义并没有太大区别,仅仅增加了parent 属性。子bean 可以没有class 属性,
若父bean 定义中有class 属性,则子bean 定义中可省略其class 属性,但子bean 将采用与父bean 相同的实现类。
测试程序修改如下:
public class BeanTest
{

public static void main(String[] args)throws Exception{
ApplicationContext ctx = new FileSysternXmlApplicationContext("bean.xml");
Person p = (Person)ctx.getBean("chinese");
p.useAxe();
}

}
程序执行结果如下:
Spring 实例化依赖bean: Stee1Axe 实例.. .
Spring实例化主调bean: Chinese 实例.. .
spring 执行依赖关系注入...
钢斧砍柴真快


另外,子bean 从父bean 定义继承了实现类并依赖bean 。但子bean 也可覆盖父bean的定义,看如下的配置文件:

//Axe 的实现类StoneAxe如下:
public class StoneAxe implements Axe

//默认构造器
public StoneAxe(){
System.out.println("Spring实例化依赖bean: StoneAxe实例.. .");
}
//实现Axe 接口的chop 方法
public String chop(){
return "石斧砍柴好慢";
}

}

Chinese子类如下:
public class Shanghai extends Chinese {

   public void show() {
                System.out.println("子Bean ,中国的上海");
    }

}


<?xm1 version="1.0" encoding="gb2312"?>
<! 指定Spring 配置文件的dtd>
<lDOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<! -- Spring 配置文件的根元素一〉
<beans>
<bean id="steelAxe" class="lee.SteelAxe"/>
<bean id="stoneAxe" class="lee.StoneAxe"/>
<!一通过abstract 属性定义该bean 是抽象bean-->
<bean id="chineseTemplate" class="lee.Chinese" abstract="true">
<property name="axe">
<ref local="steelAxe"/>
</property>
</bean>
<!一通过parent 属性定义子bean-->
<bean id="shanghai" parent="chineseTemplate">
<!一覆盖父bean 的依赖定义…〉
<property name="axe">
<ref local="stoneAxe"/>
</property>
</bean>
</beans>

此时,子bean 的依赖不再是父bean 定义的依赖了。注意,这个时候的父类lee.Chinese 不能是抽象类,(说明下:有abstract="true")不一定说明这个类一定是个抽象类,不是抽象类同样可以在Spring里定义为抽象Bean,如果你的Class是抽象类,那这个时候就不能用父Bean的Class,一定要在子Bean中定义Class来初始化这个子Bean)
测试程序修改如下:
public class BeanTest
{

public static void main(String[] args)throws Exception{
ApplicationContext ctx = new FileSysternXmlApplicationContext("bean.xml");
Person p = (Person)ctx.getBean("shanghai");
p.useAxe();
}

}

按上面的测试程序执行结果如下:
Spring 实例化依赖bean: SteelAxe 实例.. .
spring 实例化依赖bean: StoneAxe 实例.. .
Spring 实例化主调bean: Chinese 实例.. .
Spring 执行依赖关系注入...
石斧砍柴好慢


注意:上例中的子bean 定义都没有class 属性,因为父bean 定义中已有class 属性,子bean 的class 属性可从父bean 定义中继承,但需要注意的是从父Bean继承Class时,父Bean一定不能是抽象类,因为抽象类不能创建实例;如果父bean 定义中也没有指定class 属性,则子bean 定义中必须指定class 属性,否则会出错;如果父bean 定义指定了class 属性,子bean 定义也指定了class 属性,则子bean 将定义的class 属性覆盖父bean 定义的class属性。

 

 

-------------------------------------------------------------------------------------

---------------------------------------------------

Spring 中bean的继承和Java中的继承截然不同,前者是实例与实例之间的参数的延续,后者是一般到特殊的细化,前者是对象和对象之间的关系,后者是类和类之间的关系。

  a.Spring中的子bean和父bean可以是不同的类型,但是Java中的继承,子类是一种特殊的父类;

  b.Spring中的bean的继承是实例之间的关系,主要表现在参数的延续,而Java中的继承是类与类之间的关系,主要体现在方法和属性的延续。

  c.Spring中子bean不可以作为父bean使用,不具备多态性,Java中的子类实例完全可以当作父类实例使用。

分享到:
评论

相关推荐

    spring bean 属性总结

    - **abstract属性**:如果设置为`true`,则该Bean仅作为其他Bean的抽象模板,不能被直接实例化。 - **parent属性**:允许继承另一个Bean的属性。这对于共享一些通用配置非常有用。 - **autowire属性**:控制Bean的...

    Java的Spring框架中bean的继承与内部bean的注入

    这样,我们可以创建一个基础模板Bean定义,然后由其他特定需求的Bean继承,避免重复编写相同的配置。 例如,在上述的`beans.xml`配置文件中,`helloWorld` Bean定义了一个包含`message1`和`message2`属性的对象。...

    通过实例解析spring bean之间的关系

    此外,Spring还允许定义抽象Bean(abstract bean),它们不用于实例化,而是作为其他Bean的模板。一个Bean可以通过设置`abstract`属性为`true`来声明为抽象Bean,或者如果未指定`class`属性,Spring也会将其视为抽象...

    spring02-3

    当我们创建一个`abstract="true"`的bean定义时,Spring容器不会尝试创建该bean,而是将其作为其他bean的父类,让子bean继承其属性和配置。这在我们需要定义一组有共同配置的bean时非常有用,而具体实现则由子bean...

    spring配置文件:整理总结Spring中XML配

    - 为了避免重复定义相同的bean配置,Spring支持一种类似于继承的机制,即通过定义一个抽象bean来作为其他bean的基础模板。例如,创建一个抽象bean `AbstractService`,并在其他具体服务中引用它: ```xml &lt;bean ...

    spring学习笔记

    此外,Spring支持抽象bean,抽象bean不会被初始化,通常用于定义模板bean,其子bean可以继承属性并添加新属性。通过`parent`属性定义子bean,并注意某些属性不能从父bean继承,如`depends-on`、`autowire`等。 在...

    mybaits-spring(ibatis-spring)-1.0.2-bundle

    《MyBatis-Spring整合详解及1.0.2版本剖析》 MyBatis-Spring是MyBatis和Spring框架的集成库,旨在简化在Spring应用中使用MyBatis的过程,实现两者的无缝连接。本篇文章将深入探讨MyBatis-Spring的核心功能,以及...

    spring-reference1.2.pdf

    - **抽象Bean定义**:可以创建抽象Bean定义作为模板,供子Bean继承使用。 - **子Bean定义**:子Bean可以继承父Bean的配置,并覆盖或添加新的配置。 #### 3.6 与BeanFactory交互 - **获取FactoryBean**:可以使用...

    spring-3.1.0中文版api帮助文档

    - **抽象和子Bean**:讲解如何定义抽象Bean作为模板,以及如何创建具体的子Bean继承抽象Bean。 **2.12 基于注解配置DI容器** - **注解驱动**:使用注解替代XML配置,实现更简洁的依赖注入。 **2.13 Spring表达式...

    Spring-Reference_zh_CN(Spring中文参考手册)

    3.3.3. bean属性及构造器参数详解 3.3.3.1. 直接量(基本类型、Strings类型等。) 3.3.3.2. 引用其它的bean(协作者) 3.3.3.3. 内部bean 3.3.3.4. 集合 3.3.3.5. Nulls 3.3.3.6. XML-based configuration metadata ...

    spring

    Spring支持bean的重用,类似于继承的概念,允许创建抽象bean作为其他bean的模板,减少重复配置。通过设置父类bean为抽象类型(abstract="true"),并在子bean中引用父bean,可以轻松实现配置的重用和简化。 **6. ...

    spring framework 3 教程

    #### 第十章:定义Spring Bean的继承 - **Bean定义模板:** - 通过继承Bean定义来复用相同的配置,减少重复代码。 #### 第十一章:Spring依赖注入 - **基于构造函数的依赖注入:** - 通过构造函数参数传递依赖项...

    Spring ioc源码解读

    - **资源接口**:通过使用Resource接口来抽象Bean定义的数据来源,使得Bean的定义可以来自多种资源,如文件系统、网络等。 - **Bean定义读取**:Bean定义的读取过程通过委托给BeanDefinitionReader完成,例如...

    深入分析Spring源码.docx

    7. **模板方法模式**:Spring的JdbcTemplate和HibernateTemplate等模板类,通过预定义的模板方法,简化了数据库操作,遵循了模板方法模式。 8. **观察者模式**:Spring事件机制中,事件发布者和订阅者之间的交互...

    spring集成redis需要的jar包.rar

    6. 集成RedisTemplate到Spring的Bean:将`RedisTemplate`实例声明为Spring的Bean,这样其他组件可以通过依赖注入的方式使用。 7. 测试和优化:完成基本配置后,编写测试用例验证Redis的存取功能,根据实际需求考虑...

    Spring 2.0 开发参考手册

    3.3.3. bean属性及构造器参数详解 3.3.4. 使用depends-on 3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.7. 依赖检查 3.3.8. 方法注入 3.4. bean的作用域 3.4.1. Singleton作用域 3.4.2. ...

Global site tag (gtag.js) - Google Analytics