zoukankan      html  css  js  c++  java
  • Spring自动装配bean属性

    节选自《Spring in Action》64-69页

    package com.sflik.bean;
    
    /**
     * Created by sflik on 2015/7/14.
     * 诗接口
     */
    public interface Poem {
        void recite();//朗诵
    }
    package com.sflik.bean;
    
    /**
     * 短诗
     * Created by sflik on 2015/7/14.
     */
    public class Sonnet29 implements Poem{
    
        private static String[] LINES={"鹅鹅鹅,曲项向天歌,白毛浮绿水,红掌拨清波"};
    
        @Override
        public void recite() {
            for (int i = 0; i < LINES.length; i++) {
                System.out.println(LINES[i]);
            }
        }
    }
    
    
    package com.sflik.bean;

    /**
    * Created by sflik on 2015/7/14. * 乐器接口 */ public interface Instrument { public void play(); }
    
    
    package com.sflik.bean;

    /**
    * Created by sflik on 2015/7/14. * 萨克斯 */ public class Saxophone implements Instrument { public Saxophone(){ } @Override public void play() { System.out.println("TOOT TOOT TOOT !"); } }
    package com.sflik.bean;
    
    /**
     * 钢琴
     * Created by sflik on 2015/7/14.
     */
    
    public class Piano implements Instrument {
    
        @Override
        public void play() {
            System.out.println("PLINK PLINK PLINK !");
        }
    }
    
    
    package com.sflik.bean;

    /*
    *表演者接口 */ public interface Performer { void perform(); }
    
    
    package com.sflik.bean;
    /**
     * Created by sflik on 2015/7/14.
     * 演奏家出场
     */
    public class Instrumentalist implements Performer {
    
        private String name;
        private String song;
        private Instrument instrument;
      public Instrumentalist() {
    
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSong() {
            return song;
        }
    
        public void setSong(String song) {
            this.song = song;       //注入歌曲
        }
    
        public String screamSong() {
            return song;
        }
    
        public void setInstrument(Instrument instrument) {
            this.instrument = instrument;  //注入乐器
        }
    
    
        @Override
        public void perform() {
            System.out.print(name + " 演奏 " + song + ":");
            instrument.play();
        }
    }
    package com.sflik.bean;
    
    /**
     杂技师
     */
    public class Juggler implements Performer {
    
    
        private int beanBags = 3;
    
        public Juggler() {
    
        }
    
        //构造注入
        public Juggler(int beanBags) {
            this.beanBags = beanBags;
        }
    
        @Override
        public void perform() {
         System.out.println("JUGGLING "+beanBags+" BEANBAGS");
        }
    
    }
    package com.sflik.bean;
    
    /**
     * Created by sflik on 2015/7/14.
     * 诗意的杂技师
     */
    public class PoeticJuggler extends Juggler {
        private Poem poem;
    
    
        public PoeticJuggler(Poem poem) {
            super();//调用父类无参构造,3个豆袋子
            this.poem=poem;
        }
    
        public PoeticJuggler(Poem poem, int beanBags) {
          super(beanBags);
          this.poem=poem;
        }
    
        //重写父类表演方法
        @Override
        public void perform(){
            super.perform();
            System.out.println("While reciting");
            poem.recite();
    
        }
    
    
    }
    package com.sflik.test;
    
    import com.sflik.bean.*;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * 测试类
     * Created by sflik on 2015/7/14.
     */
    public class Test {
        static ApplicationContext a = new ClassPathXmlApplicationContext("spring-config.xml");  
    
        public static void instrumentailistPlay() {
            Performer p = (Performer) a.getBean("kenny2");
            p.perform();
        }
    
        public static void main(String[] args) {
    
            instrumentailistPlay();
        }
    }

        byName自动装配

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <!--萨克斯bean-->
        <bean id="instrument" class="com.sflik.bean.Saxophone"/>
    
         <!--钢琴bean-->
         <bean id="piano" class="com.sflik.bean.Piano"/>
     
    
        <!--自动装配 byName-->
        <!--byName装配:寻找上下文中id为instrument的bean和该bean的instrument属性名称匹配,
    如果上下文中存在,就把那个bean(id="instrument")装配到该Bean的instrument 属性中
    --> <!--注:通过setter注入来进行自动装配--> <bean id="kenny" class="com.sflik.bean.Instrumentalist" autowire="byName"> <property name="song" value="summer"/> <property name="name" value="kenny"/> </bean>
    </beans>

        byType自动装配

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd">
    
         <!--萨克斯bean-->
         <bean id="saxphone" class="com.sflik.bean.Saxophone"/>
    
         <!--钢琴bean-->
         <bean id="piano" class="com.sflik.bean.Piano"/>
     
         <!--自动装配 byType-->
         <!--byName装配:和byName相似,寻找上下文中id为instrument的bean和该bean的instrument类型匹配,
    如果上下文中存在,就把那个bean(id="instrument")装配到该Bean的instrument 属性中
    -->
    <!--byTpye同样使用setter注入进行自动装配--> <bean id="kenny3" class="com.sflik.bean.Instrumentalist" autowire="byType"> <property name="song" value="summer"/> <property name="name" value="kenny3"/>
    </bean>
    </beans>

     然。。。。这样编译会报错

    因为上下文中存在多个Bean(saxphone,piano)的类型是Instrument的子类

          为了避免因为使用byType自动装配而带来的歧义,Spring为我们提供了另外两种选择:

    可以使用<bean>元素的primary属性,为自动装配标识一个首选Bean,或者可以消除某个Bean自动装配的候选资格。

        但是primary属性有个很怪异的一点:它默认设置为true,这意味着所有候选Bean都变成首选Bean,那设置这个属性还有什么意义,所以为了使用primary属性,我们不得不将所有非首选Bean的primary属性设置为false.

      例如:

    <bean id="saxphone" class="com.sflik.bean.Saxophone" primary="false" />

     primary属性仅对标识首选Bean有意义,如果在自动装配时,我们希望排除某些Bean,那可以设置这些Bean的autowire-candidate属性为flase,如:

    <bean id="saxphone" class="com.sflik.bean.Saxophone" autowire-candidate="false" />

    这样spring在自动装配时忽略(saxphone)Bean作为候选Bean.

        constructor自动装配

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <!--短诗bean-->
        <bean id="sonnet29" class="com.sflik.bean.Sonnet29"/>
    
      <!--诗意的杂技师bean-->
        <bean id="duke" class="com.sflik.bean.PoeticJuggler">
            <!--配置构造参数-->
            <constructor-arg value="100"/>
            <constructor-arg ref="sonnet29"/>
        </bean>
    
    </beans>

    以前我们这样写,使用<constructor-arg>元素为Bean的构造器的参数注入值

         使用constructor自动装配的话,可以移除<constructor-arg>元素,由spring上下文自动选择Bean注入到构造器的参数中,重新声明的(duck)Bean:

     <bean id="duke" class="com.sflik.bean.PoeticJuggler" autowire="constructor"/>

         在duke Bean的新声明中,<constructor-arg>元素消失不见了,而autowire的属性设置为constructor。上述声明告诉Spring去审视PoeticJuggler的构造器,并尝试在Spring配置中寻找匹配PoeticJuggler某一构造器所有参数的Bean,上面我们定义了sonnet29 Bean,他是一个Poem,恰巧与PoeticJuggler的其中一个构造器参数相匹配,因此当duke Bean时,Spring使用这个构造器,并把sonnet29 Bean作为参数传入。

         constructor自动装配具有和byType自动装配相同的局限性。当发现多个Bean都匹配某个构造器的参数时,Spring不会猜测哪一个Bean更合适自动装配。此外,如果一个类有多个构造器,他们都满足自动装配的条件时,Spring也不会尝试猜测哪一个构造器更适合使用

       

        autodetect最佳自动装配

            如果想自动装配Bean,但是又不能决定该使用哪一种类型的自动装配。现在不用担心了,我们可以设置autowire属性为autodetect,由Spring来决定。例如:

     <bean id="duke" class="com.sflik.bean.PoeticJuggler" autowire="autodetect"/>

       当配置一个Bean的autowire属性为autodetect时,Spring会首先尝试使用constructor自动装配,如果没有发现与构造器相匹配的Bean时,Spring讲尝试使用byType自动装配。

       

       默认自动装配

          如果需要为Spring应用上下文的每一个Bean(或者其中的大多数)配置相同的autowire属性,那么就可以要求Spring为它所创建的所有Bean,应用相同的自动装配策略来简化配置。我们所需要做的仅仅是在根元素<beans>上增加一个default-autowire属性:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byType">
    
    </beans>

        默认情况下,default-autowire属性被设置为none,在这里我们讲default-autowire属性设置为byType,希望每一个Bean都使用byType自动装配。

        我们还可以使用<bean>元素的autowire属性来覆盖<beans>元素所配置的默认自动装配策略    

        

  • 相关阅读:
    301重定向 修改默认网站访问文件
    修改本地host 文件 实现多“域名”访问 host'实现FQ
    thinkphp3.2.3 整合 富文本编辑器
    thinkphp3.2.3 跨数据库查询
    git 码云上关联仓库 克隆代码
    PHP GD库中输出图像乱码问题
    mysql 新建用户
    
    算法思想:
    算法思想:
  • 原文地址:https://www.cnblogs.com/sflik/p/4807677.html
Copyright © 2011-2022 走看看