Spring Framework Core(1)-The Ioc Container(3)

1 IoC 容器

1.4.3 使用depends-on

如果一个bean是另一个bean的依赖项,这通常意味着将一个bean设置为另一个bean的属性。通常使用基于xml的配置元数据中的<ref/>元素来完成此任务。然而,有时候bean之间的依赖关系不那么直接。例如,当需要触发类中的静态初始化器时,例如注册数据库驱动程序时。依赖属性可以显式地强制在使用此元素的bean初始化之前对一个或多个bean进行初始化。下面的示例使用depends-on属性来表示对单个bean的依赖:

<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />

为了表示对多个bean的依赖,提供一个bean名称列表作为依赖属性的值(逗号、空格和分号是有效的分隔符):

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

depends-on属性既可以指定一个初始化时间依赖项,在单例模式Bean的情况时,也可以指定一个对应的销毁时依赖项。与给定bean定义依赖关系的依赖bean首先被销毁,先于给定bean本身被销毁。因此,依赖也可以控制销毁顺序。

1.4.3 延迟加载Beans

默认情况下,ApplicationContex会尽快实现创建和配置所有单例Beans 来作为初始化过程的一部分。通常,这种预实例化是可取的,因为配置或周围环境中的错误会立即被发现,而不是几小时甚至几天之后。当此行为不可取时,您可以通过将bean定义标记为延迟初始化来防止单例bean的预实例化。延迟初始化的bean告诉IoC容器在第一次请求时创建bean实例,而不是在启动时。
在XML中,这种行为是由元素上的lazy-init属性控制的,如下面的示例所示:

<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.something.AnotherBean"/>

当前面的配置被ApplicationContext使用时,当ApplicationContext启动时,lazy bean不会被预先实例化,而not.lazy bean会立即预先实例化。
然而,当延迟初始化的bean是未延迟初始化的单例bean的依赖项时,ApplicationContext在启动时创建延迟初始化的bean,因为它必须满足单例的依赖项。延迟初始化的bean被注入到一个没有延迟初始化的单例bean中。
您还可以使用元素上的default-lazy-init属性来控制容器级别的延迟初始化,如下面的示例所示:

<beans default-lazy-init="true">
    <!-- no beans will be pre-instantiated... -->
</beans>

1.4.5 自动装配协作者

Spring容器可以自动创建协作bean之间的关系。通过检查ApplicationContext的内容,您可以让Spring为您的bean自动解析协作者(其他bean)。自动装配有以下优点:

  • 自动装配可以大大减少指定属性或构造函数参数的需要。在这方面,本章其他地方讨论的其他机制(如bean模板)也很有价值。
  • 自动装配可以随着对象的演化更新配置。例如,如果需要向类添加依赖项,则可以自动满足该依赖项,而不需要修改配置。因此,自动装配在开发过程中特别有用,当代码库变得更加稳定时,自动装配可以无需否定切换到显式连接的选项。
    在使用基于xml的配置元数据(请参阅依赖项注入)时,可以使用<bean/>元素的autowire属性为bean定义指定autowire模式。自动装配功能有四种模式。您可以为每个bean指定自动装配,因此可以选择自动装配哪些bean。下表描述了四种自动装配模式:
ModeExplanation
no(默认)没有自动装配。Bean引用必须由ref元素定义。对于较大的部署,不建议更改默认设置,因为显式地指定协作者可以提供更好的控制和清晰度。在某种程度上,它记录了一个系统的结构。
byName通过属性名自动装配。Spring寻找与需要自动装配的属性同名的bean。例如,如果一个bean定义被按名称设置为自动装配,并且它包含一个主属性(也就是说,它有一个setMaster(…)方法),Spring会查找一个名为master的bean定义并使用它来设置属性。
byType如果容器中恰好存在该属性类型的一个bean,则允许自动获取该属性。如果存在多个,则抛出一个致命异常,这表明您不能为该bean使用byType自动装配。如果没有匹配的bean,则什么也不会发生(属性没有设置)。
constructor类似于byType,但适用于构造函数参数。如果容器中没有一个构造函数参数类型的bean,则会引发致命错误。

使用byType或构造函数自动装配模式,您可以连接数组和类型化集合。在这种情况下,将提供容器中与预期类型匹配的所有autowire候选对象,以满足依赖性。如果期望的键类型是String,则可以自动装配强类型映射实例。自动装配映射实例的值由所有匹配期望类型的bean实例组成,映射实例的键包含相应的bean名称。

自动装配的局限性和缺点

自动装配在跨项目一致使用时效果最好。如果通常不使用自动装配,那么开发人员使用它来连接一个或两个bean定义可能会感到困惑。

考虑自动装配的局限性和缺点:

  • 属性和构造参数设置中的显式依赖项总是覆盖自动装配。您不能自动装配简单的属性,如基本类型、Strings和Classes(以及这些简单属性的数组)。这种限制是由设计造成的。
  • 自动装配不如显式连接精确。尽管如前面的表中所述,Spring小心地避免猜测,以免产生可能产生意外结果的歧义。spring管理对象之间的关系不再明确记录。
  • 装配信息可能对从Spring容器生成文档的工具不可用。
  • 容器中的多个bean定义可能与要自动装配的setter方法或构造函数参数指定的类型匹配。对于数组、集合或map实例,这不一定是个问题。然而,对于期望单个值的依赖项,这种模糊性不是任意解决的。如果没有唯一的bean定义可用,则抛出异常。

在后面的应用场景中, 你有以下几个选择:

  • 放弃自动装配,支持显式装配。
  • 通过将bean定义的autowire-candidate属性设置为false来避免自动装配,如下一节所述
  • 通过将其<bean/>元素的primary设置为true,将单个bean定义指定为主候选。
  • 实现基于注解的配置提供的更细粒度的控制,如Annotation-based Container Configuration.所述。

从自动装配中排除一个Bean

在每个bean的基础上,可以将bean排除在自动装配之外。在Spring的XML格式中,将元素的autowire-candidate属性设置为false。容器使特定的bean定义对自动装配基础设施(包括诸如@Autowired之类的注释样式配置)不可用。

autowire-candidate属性被设计为只影响基于类型的自动装配。它不会影响按名称显式引用,即使指定的bean没有标记为autowire候选bean,也会解析这些引用。因此,如果名字匹配,自动装配仍然会注入一个bean。

您还可以根据bean名称的模式匹配来限制自动装配候选对象。顶级、元素在其default-autowire-candidate属性中接受一个或多个模式。例如,要将autowire候选状态限制为名称以Repository结尾的任何bean,请提供一个值*Repository。要提供多个模式,请在逗号分隔的列表中定义它们。bean定义的autowire-candidate属性的显式值true或false总是优先。对于这样的bean,不适用模式匹配规则。

这些技术对于那些您不希望通过自动装配将其注入到其他bean中的bean非常有用。这并不意味着不能通过使用自动装配来配置被排除的bean。相反,bean本身不是自动装配其他bean的候选对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值