zoukankan      html  css  js  c++  java
  • Spring Framework--Ioc Container(1)--Dependencies(2)--depends-on、lazy-init、autowire、mothod injection

    三、使用depends-on属性

    bean标签的depends-on属性,表示一个bean需要依赖另外的bean,但是他们之间没有很直接的从属关系(如一个bean是另一个bean的属性),使用了这个属性的bean在初始化本身之前,必须先初始化它depends-on的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" />

    四、bean的延迟初始化

    默认情况下,Spring在初始化Ioc容器(ApplicationContext)的时候会初始化所有的单例bean。通过设置bean标签的lazy-init属性,可以设置一个bean不在Ioc容器初始化的时候也被初始化,而是在这个bean第一次使用的时候才进行初始化。如:

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

    我们可以在容器级别来设置所有单例bean都使用延迟初始化,方法是通过使用beans根标签的default-lazy-init属性,如:

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

    五、依赖的自动装配(Autowiring collaborators)

    Spring可以自动在Ioc容器中检查bean之间的关系,进而自动地建立bean之间的依赖关系。自动装配bean有优点也有其不足之处,由用户自己决定是否使用这个功能。

    自动装配的xml配置,是通过bean标签的autowire属性实现的。有五种autowire模式:

    no  --默认的,不自动装配,依赖通过常规的ref标签来配置

    byName  --通过属性名字自动装配,比如一个bean设置了通过byName方式自动装配,那么Spring会在Ioc容器中查找以这个bean的属性命名的其他bean,并作为这个bean的依赖注入。

    byType  --和byName类似,但是是通过属性的类型来查找依赖的。这必须要求在容器中最多只存在唯一一个这种类型的bean,否则会抛出异常。如果不存在,那么没有依赖被注入。

    constructor  --和byType类似,不过是根据构造函数的参数类型来查找依赖的,同样,一种类型的bean最多只能存在一个,否则有致命错误发生。

    使用byType和constructor模式自动装配,你可以自动装配一个数组或者强类型的集合类,这种情况下,所有类型匹配的bean会作为依赖放到集合里去。如果自动装配一个强类型的Map,并且key的类型为String,那么容器中所有bean类型匹配Map的值类型的bean就会注入到这个Map,键值为对应的bean的名字。

    设置bean标签的autowire-candidate属性为false,可以让一个bean不能作为候选的依赖自动装配到其他的bean中。

    设置bean标签的primary属性为true,可以配置一个bean作为主要的候选依赖可以自动装配到其他bean中。

    在beans根标签上设置default-autowire-candidate属性,可以指定容器中bean的命名符合某些模式的bean才参与自动装配,比如把该属性设置为*Repository,那么就只有bean的名字以Repository结尾的bean才可能被自动装配到别的bean中去。

    六、方法注入 (Method Injection)

    前面讲的都是bean与bean之间的依赖,即我们可以把一个bean注入到另一个bean中。除此之外,Spring还可以把一个bean的方法注入到另一个bean中去实现或者覆盖这个bean中方法。

    (1)Lookup Method Injection: Spring可以利用CGLIB库的字节码生成能力来自动生成一个类的子类,并且通过注入一个方法来重写父类的抽象方法。

    这种注入方式,必须要求父类及其需要重写的方法不能是final方法。Spring从3.2开始已经重写对CGLIB库进行了打包(在spring-core jar包里),不在需要在类路径下添加CGLIB的库。

    举例如下:

    package fiona.apple;
    // no more Spring imports!
    public abstract class CommandManager {
        public Object process(Object commandState) {
        // grab a new instance of the appropriate Command interface
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
        }
        // okay... but where is the implementation of this method?
        protected abstract Command createCommand();
    }

    通过以下xml配置,CommandManager类中的createCommand方法被AsyncCommand类的方法实现了,就是方法注入。Spring是通过动态生成了CommandManager的子类来实现的。

    <!-- a stateful bean deployed as a prototype (non-singleton) -->
    <bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
    <!-- inject dependencies here as required -->
    </bean>
    <!-- commandProcessor uses statefulCommandHelper -->
    <bean id="commandManager" class="fiona.apple.CommandManager">
        <lookup-method name="createCommand" bean="command"/>
    </bean>

    这种方法注入解决的现实问题就是,一个单例(singleton)bean与原型(prototype)bean之间的依赖。使得单例中每次需要原型bean的时候,容器都是重新初始化一个新的bean给单例bean使用。

    (2)Arbitrary Method replacement: Spring还提供了一种不怎么常用的方法注入方式,那就是任意方法替换,用一个bean中方法,替换另一个bean中的方法。实现方法是如下:

    假设下面这个类中方法需要替换:

    public class MyValueCalculator {
        public String computeValue(String input) {
        // some real code...
        }
        // some other methods...
    }

    我们定义另外一个类,实现这个特定的接口:org.springframework.beans.factory.support.MethodReplacer

    /**
    * meant to be used to override the existing computeValue(String)
    * implementation in MyValueCalculator
    */
    public class ReplacementComputeValue implements MethodReplacer {
        public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
            // get the input value, work with it, and return a computed result
            String input = (String) args[0];
            ...
            return ...;
        }
    }

    最后在xml中配置如下:

    <bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
    <!-- arbitrary method replacement -->
        <replaced-method name="computeValue" replacer="replacementComputeValue">
            <arg-type>String</arg-type>
        </replaced-method>
    </bean>
    <bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>    

    可以定义多个<arg-type>标签元素来指定需要替换的方法的参数类型。为了方便,这个标签的值可以使用类型的简写形式,比如String, Str, java.lang.String都可以用来表示字符串类型参数。

  • 相关阅读:
    Mysql支持的数据类型
    JavaScript 原型中的哲学思想
    99%的人都理解错了HTTP中GET与POST的区别
    Let's Encrypt,站点加密之旅
    说说cglib动态代理
    说说Java代理模式
    RESTful API 编写指南
    RESTful 架构风格概述
    Centos 6 搭建安装 Gitlab
    超详细的阿里字节Spring面试技术点总结(建议收藏)
  • 原文地址:https://www.cnblogs.com/winson/p/3680576.html
Copyright © 2011-2022 走看看