Spring-注入

Spring-注入

1.属性注入

  属性注入即通过setXxxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。

  属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化对象,然后通过反射的方式调用Setter方法注入属性值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Cat {
private String color;
private int age;
private int weigth;
private People people;

public Cat(){ }

public void setColor(String color) {
this.color = color;
}

public void setAge(int age) {
System.out.println("有setAge方法但是没有设置属性!");
}

public void setWeigth(int weigth) {
this.weigth = weigth;
}

public int getWeigth() {
return weigth;
}

public String getColor() {
return color;
}
}

Cat类中定义了3个属性,并分别提供了对应的Setter方法和默认构造函数。


配置文件中对cat进行属性注入

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" //p命名空间,简化配置
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="c" class="com.smart.model.Cat"
p:weigth="50"
p:age="4"
p:color="白色"
p:people-ref="p"
/>
<bean id="p" class="com.smart.model.People"/>
</beans>

测试

1
2
3
4
5
6
7
8
public class test {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans/cat.xml");
Cat c=ctx.getBean("c", Cat.class);
System.out.println("使用ClassPathXmlApplicationContext启动Spring容器");
System.out.println(c.getAge()+" "+c.getColor()+" "+c.getWeigth());
}
}

输出:

PS:Spring只会检查Bean中是否有对应的Setter方法,至于Bean中是否有对应的属性变量则不做要求。如上面。


2.构造函数注入

  构造函数注入是除属性注入之外的另一种常用的注入方式,它保证一些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使用。

  1. 按类型匹配入参

    如此构造函数:

    1
    2
    3
    4
    public Cat(String name,double price){
    this.name=name;
    this.price=price;
    }

    配置:

    1
    2
    3
    4
    <bean id="c3" class="com.smart.model.Cat">
    <constructor-arg type="java.lang.String" value="旺财"/>
    <constructor-arg type="double" value="20"/>
    </bean>

  2. 按索引匹配入参

    如此构造函数:第二个和第三个都是int类型

    1
    2
    3
    4
    5
    public Cat(String color, int age, int weigth) {
    this.color = color;
    this.age = age;
    this.weigth = weigth;
    }

    配置:

    1
    2
    3
    4
    5
    <bean id="c4" class="com.smart.model.Cat">
    <constructor-arg index="0" value="紫色"/>
    <constructor-arg index="1" value="4"/>
    <constructor-arg index="2" value="30"/>
    </bean>

  3. 联合使用类型和索引匹配入参

    如下面两个构造函数:需要联合使用type和index才能确定配置项和构造函数入参的对应关系。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public Cat(String color, int age, int weigth) {
    this.color = color;
    this.age = age;
    this.weigth = weigth;
    }
    public Cat(String color, int age, double price) {
    this.color = color;
    this.age = age;
    this.price = price;
    }

    配置:配置第二个构造函数

    1
    2
    3
    4
    5
    <bean id="c5" class="com.smart.model.Cat">
    <constructor-arg index="0" type="java.lang.String" value="蓝色"/>
    <constructor-arg index="1" type="int" value="3"/>
    <constructor-arg index="2" type="double" value="600"/>
    </bean>

  4. 通过自身类型反射匹配入参

    如果Bean构造函数入参的类型是可辨别的(其他的Bean),由于Java反射机制可以获取构造函数入参的类型,即使构造函数注入的配置不提供类型和索引的信息,Spring依旧可以正确地完成构造函数的注入工作。

    如下面People类的构造函数:

    1
    2
    3
    4
    5
    6
    public People(String name, int age, Cat c, Dog d) {
    this.name = name;
    this.age = age;
    this.c = c;
    this.d = d;
    }

    配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <bean id="p" class="com.smart.model.People">
    <constructor-arg value="老GS"/>
    <constructor-arg value="21"/>
    <constructor-arg ref="d4"/>//引用其他Bean
    <constructor-arg ref="c4"/>//引用其他Bean
    </bean>
    <bean id="c4" class="com.smart.model.Cat"
    p:weigth="40"
    p:color="橘色"
    p:age="2"
    />
    <bean id="d4" class="com.smart.model.Dog"
    p:weigth="30"
    p:color="白色"
    p:age="3"
    />

    执行:

    1
    2
    People p1=cxt.getBean("p", People.class);
    System.out.println(p1.getName()+" "+p1.getC().getColor()+" "+p1.getD().getColor());

    **输出: ** 老GS  橘色  白色


    注入集合类型属性

    1. List

      为People添加一个List类型的hobby属性并添加setter。

      1
      2
      3
      4
      private List favorites=new ArrayList();
      public void setFavorites(List favorites) {
      this.favorites = favorites;
      }

      Xml:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <bean id="p2" class="com.smart.model.People">
      <property name="favorites">
      <list>
      <value>rap</value>
      <value>唱</value>
      <value>跳</value>
      <value>打篮球</value>
      </list>
      </property>
      </bean>

      执行:

      1
      2
      People p2=cxt.getBean("p2", People.class);
      System.out.println(p2.getFavorites());

      输出:rap, 唱, 跳, 打篮球

      List属性既可以通过< value >出入字符串,也可以通过< ref >注入容器中的其他Bean。


    2. Map

      为People添加一个Map类型的work属性并添加setter:

      1
      2
      3
      4
      5
      private Map work=new HashMap();

      public void setWork(Map work) {
      this.work = work;
      }

      Xml

      1
      2
      3
      4
      5
      6
      7
      8
      <bean id="p3" class="com.smart.model.People">
      <property name="work">
      <map>
      <entry key="9点" value="上课"/>
      <entry key="18点" value="放学"/>
      </map>
      </property>
      </bean>

      执行

      1
      2
      People p2=cxt.getBean("p3", People.class);
      System.out.println(p2.getWork());

      输出:9点=上课, 18点=放学

      假如某一Map元素的键和值都是对象,则采取以下配置:

      1
      2
      3
      4
      <entry>
      <key><ref bean="keyBean"></ref></key>
      <ref bean="valueBean"></ref>
      </entry>

    通过util命名空间配置集合类型的Bean

      如果希望配置一个集合类型的Bean,而非一个集合类型的属性,则可以通过util命名空间进行配置。

    Xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"//引入util命名空间
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util //util:list声明
    http://www.springframework.org/schema/util/spring-util.xsd //util:list声明
    ">
    <util:list id="list1" list-class="java.util.LinkedList">
    <value>看电视</value>
    <value>玩游戏</value>
    <value>运动</value>
    </util:list>

    <util:set id="set1">
    <value>看电视</value>
    <value>玩游戏</value>
    <value>运动</value>
    </util:set>

    <util:map id="map1">
    <entry key="9点" value="吃饭"/>
    <entry key="18点" value="吃晚饭"/>
    </util:map>
    </beans>

    测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import java.util.List;
    import java.util.Map;
    import java.util.Set;

    public class test3 {
    public static void main(String[] args) {
    ApplicationContext cxt=new ClassPathXmlApplicationContext("beans/util.xml");
    List list=cxt.getBean("list1",java.util.LinkedList.class);
    Set set=cxt.getBean("set1",java.util.Set.class);
    Map map=cxt.getBean("map1",java.util.Map.class);
    System.out.println(list+" "+set+" "+map);
    }
    }

    输出: [看电视, 玩游戏, 运动]  [看电视, 玩游戏, 运动]  {9点=吃饭, 18点=吃晚饭}


    自动装配

      < bean >元素提供了一个指定自动装配类型的属性:**autowire=”<自动装配类型>”**。Spring提供了4种自动装配类型。

    1. byName

        根据名称进行自动匹配。假设People有一个名为cat的属性,如果容器中刚好有一个名为car的Bean,Spring就会自动将其装配给People的cat属性。

    2. byType

        根据类型进行自动匹配。假设People有一个名为cat的属性,如果容器中刚好有一个Cat类型的Bean,Spring就会自动将其装配给People的cat属性。

    3. constructor

        与byType类似,只不过它是针对构造函数注入而言的,假设People有一个构造函数,构造函数包含一个Cat类型的入参,如果容器中有一个Cat类型的Bean,则Spring将自动把这个Bean作为People构造函数的入参,如果容器中没有找到和构造函数入参匹配类型的Bean,Spring抛出异常。

    4. autodetect

        根据Bean的自省机制决定采用byType还是constructor进行自动装配:如果Bean提供了默认的构造函数,则采用byType;否则采用constructor。


如将上面id=”p”的Bean改为:

1
2
3
<bean id="p" class="com.smart.model.People"
p:name="老GS"
autowire="byType"/>

执行:

1
2
People p1=cxt.getBean("p", People.class);
System.out.println(p1.getName()+" "+p1.getC().getColor()+" "+p1.getD().getColor());

**输出: **老GS  橘色  白色

可见,容器自动将c4、d4注入了。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×