详解Spring Bean 之间的特殊关系
在Spring容器中,两个Bean之间除了通过建立依赖关系外,还存在着一些特殊关系。
1继承
在面向对象的编程原理中,当多个类拥有相同的方法和属性时,则可以引入父类用于消除重复的代码。而在Spring容器中,如果多个Bean存在相同的配置信息,我们可以定义一个父Bean,这样子Bean将会自动继承父Bean的配置信息。
一般情况下,父Bean的功能是简化子Bean的配置,所以设置为抽象类(abstract="true");如果这里没有把父Bean设置为抽象类,那么Spring容器会实例化父Bean。
2前置依赖
一般情况下,使用来建立Bean之间的依赖关系,Spring容器负责管理这些关系,当实例化一个Bean时,容器保证该Bean所依赖的Bean都已经完成了初始化工作。
但在某些情况下,Bean之间的依赖关系并没有那么明显。
假设这样一种场景,某系统设置了一些系统参数(如密码有效期、是否开启监控等),这些启动参数用来控制系统的运行逻辑,我们使用一个Setting类来表示这些参数:
publicclassSettings{ /** *密码过期时间(单位:天) */ publicstaticintPASS_TIMEOUT=30; /** *是否开启监控 */ publicstaticbooleanIS_MONITOR=false; }
在此,我们为这些参数设置了默认值。系统还有一个管理后台,管理员可以通过这个后台调整这些系统参数并保存到数据库中。所以应用启动时,需要从数据库中加载这些系统参数:
publicclassSystem{ publicSystem(){ init(); } /** *初始化 */ privatevoidinit(){ //假设这些值来源于数据库 Settings.PASS_TIMEOUT=20; Settings.IS_MONITOR=true; } }
系统有一个密码过期管理器,它会根据系统参数中的【密码过期的天数】,来创建检测密码是否过期的定时任务:
publicclassPassManager{ inttimeout; publicPassManager(){ timeout=Settings.PASS_TIMEOUT; timerTask(); } /** *检测密码是否过期的定时任务 */ privatevoidtimerTask(){ } publicintgetTimeout(){ returntimeout; } }
虽然PassManager并没有直接依赖于Settings,但从逻辑上来看,PassManager希望System加载初始化系统参数后再启动。
Spring中可以通过depends-on属性显式地指定Bean的前置依赖Bean,保证这个Bean在实例化之前,它的前置依赖Bean已经加载完毕。
如果前置依赖于多个Bean,那么可以通过逗号、空格或分号的方式来配置Bean名称。
3引用ID
假设一个Bean需要引用另一个Bean的id值(beanName),这一般用于在运行期间在Bean中通过getBean(beanName)方法获取另一个Bean的情境。
可以这样配置:
Book中新增authorId属性:
/** *authorBean的ID */ privateStringauthorId;
虽然可以以这种字面值的形式进行设置,但两者之间并没有建立真正的引用关系。所以只有等到具体调用时才会发现配置错误。
Spring提供了
如果配置发生错误,Spring容器启动时就会抛出BeanDefinitionStoreException,而且IDE的XML分析器也会提前发现引用错误,所以推荐使用
总结
以上所述是小编给大家介绍的SpringBean之间的特殊关系,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!