Spring中bean的继承与抽象代码示例
我们在应用Spring时,在一般的设计时,肯定要用的抽象类。那在Spring中怎么样配置这些抽象Bean呢。请看下面:
如果两个bean之间的配置信息非常相似,可利用继承来减少重复配置工作。
继承是指子bean定义可从父bean定义继承部分配置信息,也可覆盖特定的配置信息,或者添加一些配置。使用继承配置可以节省很多的配置工作。在实际应用中,通用配置会被配置成模板,可供子bean继承。
使用abstract属性
正如前面所介绍的,通用的配置会被配置成模板,而模板不需要实例化,仅仅作为子bean定义的模板使用。而ApplicationContext默认预初始化所有的singletonbean。使用abstract属性,可以阻止模板bean被预初始化。abstract属性为true的bean称为抽象bean,容器会忽略所有的抽象bean定义,预初始化时不初始化抽象bean。如果没有定义abstract属性,该属性默认为false。如下配置文件定义了一个抽象bean,该抽象bean作为模板使用:
publicclassSteelAxeimplementsAxe { //count是个状态值,每次执行chop方法该值增加1 privateintcount=0; publicSteelAxe(){ System.out.println("Spring实例化依赖bean:SteelAxe实例..."); } //测试用方法 publicStringchop(){ return"钢斧砍柴真快"+++count; } } publicclassChineseimplementsPerson //面向Axe接口编程,而不是具体的实现类 privateAxeaxe; //默认的构造器 publicChinese(){ System.out.println("Spring实例化主调bean:Chinese实例..."); } //设值注入所需的setter方法 publicvoidsetAxe(Axeaxe){ System.out.pr工ntln("Spring执行依赖关系注入..."); this.axe=axe; } //实现Person接口的useAxe方法 publicvoiduseAxe(){ System.out.println(axe.chop()); } }
从配置文件中可以看出,抽象bean的定义与普通bean的定义几乎没有区别,仅仅增加abstract属性为true,但主程序执行结果却有显著的差别。下面的主程序采用AppliactionContext作为Spring容器,AppliationContext默认预初始化所有的singletonbean。其主程序部分如下:
publicclassBeanTest { publicstaticvoidmain(String[]args)throwsException{ ApplicationContextctx=newFileSysternXmlApplicationContext("bean.xml"); } } //主程序部分仅仅实例化了ApplicationContext,在实例化ApplicationContext时,默认实例化singletonbean。
程序执行结果如下:
Spring实例化依赖bean:SteelAxe实例...
容器并没有实例化chineseTemplatebean,而忽略了所有声明为abstract的beano如果取消abstract属性定义,则程序执行结果如下:
Spring实例化依赖bean:SteelAxe实~J...
Spring实例化主调bean:Chinese实例...
Spring执行依赖关系注入...
可以看出,抽象bean是一个bean模板,容器会忽略抽象bean定义,因而不会实例化抽象bean。但抽象bean无须实例化,因此可以没有class属性。如下的配置文件也有效:
注意:抽象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属性值为父beanid。修改上面的配置文件如下,增加了子bean定义:
此时,子bean的依赖不再是父bean定义的依赖了。注意,这个时候的父类lee.Chinese不能是抽象类,(说明下:有abstract="true")不一定说明这个类一定是个抽象类,不是抽象类同样可以在Spring里定义为抽象Bean,如果你的Class是抽象类,那这个时候就不能用父Bean的Class,一定要在子Bean中定义Class来初始化这个子Bean)
测试程序修改如下:
publicclassBeanTest { publicstaticvoidmain(String[]args)throwsException{ ApplicationContextctx=newFileSysternXmlApplicationContext("bean.xml"); Personp=(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的继承与抽象代码示例的内容就到这里,希望对大家有所帮助。有兴趣的朋友可以参阅本站其他专题,精彩不断。感谢大家对本站的支持!