1.4.3:使用依赖:(depend-on)
如果一个 bean 是另一个 bean 的依赖项,则通常意味着将一个 bean 设置为另一个 bean 的属性。通常,您可以使用基于 XML 的配置元数据中的 element完成此操作。但是,有时 bean 之间的依赖性不太直接。(即仅有依赖性但并不为相互的引用)。depends-on属性可以在初始化使用此元素的 bean 之前显式强制初始化一个或多个 bean。
要表示对多个 bean 的依赖性,请提供一个 bean 名称列表作为depends-on属性的值(逗号,空格和分号是有效的分隔符):
1.4.4:懒初始化bean:
默认情况下,作为初始化的一部分,Application Context将会创建和配置所有的单例范围的bean(即只创建一次的bean)。如果不想这样,通过bean定义标记为延迟初始化防止单例bean的预实例化。延迟初始化的 bean 告诉 IoC 容器在首次请求时而不是在启动时创建一个 bean 实例。
在 XML 中,此行为由元素上的lazy-init属性或元素上的default-lazy-init属性控制,如以下示例所示:
但是,当延迟初始化的 bean 是未延迟初始化的单例 bean 的依赖项时,ApplicationContext将在启动时创建延迟初始化的 bean,因为它必须满足单例的依赖关系。延迟初始化的 bean 被注入到其他未延迟初始化的单例 bean 中。
1.4.5:自动布线合作者:
Spring 容器可以自动装配协作 bean 之间的关系。
自动装配的优点:
自动装配能大大减少指定属性或构造函数参数的需要;
随着对象的发展(例如添加了个属性为其他类的对象),自动装配可以自动更新配置。
使用基于 XML 的配置元数据时,可以使用元素的autowire属性为 bean 定义指定自动装配模式。您可以为每个 bean 指定自动装配,因此可以选择要自动装配的装配。下表描述了四种自动装配模式:
自动装配的局限性和缺点:
-
property和constructor-arg设置中的显式依赖项始终会覆盖自动装配。
-
自动装配不如显式接线精确。
-
接线信息可能不适用于可能从 Spring 容器生成文档的工具。
-
容器内的多个 bean 定义可能与要自动装配的 setter 方法或构造函数参数指定的类型匹配。对于数组,集合或Map实例,这不一定是问题。但是,对于需要单个值的依赖项,不会任意解决此歧义。如果没有唯一的 bean 定义可用,则引发异常。
对于4选择:
-
放弃自动布线,转而使用明确的布线。
-
通过将其元素的primary属性设置为true,将单个 bean 定义指定为主要候选对象。
-
通过基于注解的配置实现更细粒度的控件。
-
通过将其autowire-candidate属性设置为false来避免自动装配 bean 的类型。
从自动装配中排除bean:
在每个 bean 的基础上,您可以从自动装配中排除一个 bean。使用 Spring 的 XML 格式,将元素的autowire-candidate属性设置为false。容器使特定的 bean 定义对于自动装配基础结构不可用。autowire-candidate属性旨在仅影响基于类型的自动装配。它不会影响按名称显示的显式引用。如果名称匹配,按名称自动装配仍会注入 Bean。
您还可以基于与 Bean 名称的模式匹配来限制自动装配候选。顶级元素在其default-autowire-candidates属性内接受一个或多个模式。例如,要将自动装配候选状态限制为名称以Repository结尾的任何 bean,请提供值*Repository。要提供多种模式,请在以逗号分隔的列表中定义它们。 Bean 定义的autowire-candidate属性的true或false的显式值始终优先。对于此类 bean,模式匹配规则不适用。
这些技术对于您不希望通过自动装配将其注入其他 bean 的 bean 非常有用。这并不意味着排除的 bean 本身不能使用自动装配进行配置。
1.4.6:方法注入:
当单例 Bean 需要与另一个单例 Bean 协作或非单例 Bean 需要与另一个非单例 Bean 协作时,通常可以通过将一个 Bean 定义为另一个 Bean 的属性来处理依赖性。故当 bean 的生命周期不同时会出现问题。假设单例 bean A 需要使用非单例(原型)bean B,也许在 A 的每个方法调用上都使用。容器仅创建一次单例 bean A,因此只有一次机会来设置属性。
一个解决方案是放弃某些控制反转。您可以通过实现ApplicationContextAware接口来使 bean A 知道容器,并在每次 bean A 需要beanB时对容器进行 getBean(“ B”)调用询问(通常是新的)bean B 实例。以下示例显示了此方法:
查找方法注入(Lookup method inject):
上面的代码是每次都从applicationContext重新获取一个新实例来实现的。Spring提供了一个Lookup method inject机制,它可以改变方法的返回值,来达到方法注入的效果。对应的有annotation和xml两种使用方式。
annotation的使用方式@Lookup,把@Lookup加到你要改变方法返回值的方法上:
Loopup的注释中的写明了需要返回的bean名字,如果没有写bean name,那么会根据createCommand的函数返回值类型去查找对应的bean
Spring的Lookup method inject实现原理的是使用CGLIB动态生成一个类去继承CommandManager,重写createCommand方法。然后根据@Lookup中指定的bean Name或者createCommand方法的返回类型判断需要返回的bean。createCommand可以是abstract和可以不是。因为使用的是继承,所以CommandManager类和createCommand方法都不能是final的。
对应实现的XML配置:
任意方法替换(Arbitrary method replacement):
Lookup method inject只是改变了方法的返回值,但是method replacement可以替换bean 容器里任意方法的实现,达到方法的完全注入,一般情况下不要这个使用特性!
此特性,只能基于XML配置实现。
假如我们要替换如下类的computeValue方法:
第一步,我们要现实org.springframework.beans.factory.support.MethodReplacer接口:
第二步,在XML中,使用replaced-method元素进行配置.:
在上面的xml中,在元素replaced-method中使用了arg-type。它的作用是在有多个方法重载时,根据arg-type中指定的参数class名字来确定具体替换哪一个方法。