简单理解

自动装配,就是将一个Bean注入到其他Bean的Property中。Spring框架式默认不支持自动装配的,要想使用自动装配需要修改spring配置文件中<bean>标签的autowire属性

代码样例

package com.spring.auto.autowire;

public class Cat {
    public void sayCat(){
        System.out.println("猫叫");
    }
}
package com.spring.auto.autowire;

public class Dog {
    public void sayDog(){
        System.out.println("狗叫");
    }
}
package com.spring.auto.autowire;

public class Person {

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public String getSay() {
        return say;
    }

    public void setSay(String say) {
        this.say = say;
    }

    private Dog dog;
    private Cat cat;
    private String say;
}
package com.spring.auto.autowire;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/spring/auto/autowire/spring_autowire.xml");
        Person person = (Person) applicationContext.getBean("test");
        person.getCat().sayCat();
        person.getDog().sayDog();
        System.out.println(person.getSay());
    }
}

 五种自动装配模式

1、no 

该模式表示默认情况下,不自动装配,通过“ref”attribute手动设定。

例如:

<bean id="cat_c" class="com.spring.auto.autowire.Cat"></bean>
    <bean id="dog_d" class="com.spring.auto.autowire.Dog"></bean>
    <bean id="test" class="com.spring.auto.autowire.Person">
        <property name="cat" ref="cat_c"/>
        <property name="dog" ref="dog_d"/>
        <property name="say" value="测试"/>
    </bean>

2、byName

该模式表示根据Property的Name自动装配,如果一个bean的name,和另一个bean中的Property的name相同,则自动装配这个bean到Property中。当一个bean节点带有 autowire byName的属性时,将查找其类中所有的set方法名,获得将set去掉并且首字母小写的字符串,然后去spring容器中寻找是否有此字符串名称id的对象。如果有,就取出注入;如果没有,就报空指针异常。

例如:

<bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
    <bean id="dog" class="com.spring.auto.autowire.Dog"></bean>
    <bean id="test" class="com.spring.auto.autowire.Person" autowire="byName">
        <property name="say" value="测试"/>
    </bean>

如果将如果将bean id="cat'的值改成bean id="catname",执行时报空指针Exception in thread "main" java.lang.NullPointerException   at com.spring.auto.autowire.Test.main(Test.java:11)。因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。

3、byType 

该模式表示根据Property的数据类型(Type)自动装配,Spring会总动寻找与属性类型相同的bean,若一个bean的数据类型,兼容另一个bean中Property的数据类型,则自动装配。

注意:使用byType首先需要保证同一类型的对象,在spring容器中唯一,若不唯一会报不唯一的异常。

例如:

<bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
    <bean id="dog" class="com.spring.auto.autowire.Dog"></bean>
    <bean id="test" class="com.spring.auto.autowire.Person" autowire="byType">
        <property name="say" value="测试"/>
    </bean>

若配置文件中有两个类型相同的bean

  <bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
    <bean id="cat_c" class="com.spring.auto.autowire.Cat"></bean>

一旦配置如上,有两种相同数据类型的bean被配置,将抛出UnsatisfiedDependencyException异常:警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'test' defined in class path resource [com/spring/auto/autowire/spring_autowire.xml]: Unsatisfied dependency expressed through bean property 'cat'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.spring.auto.autowire.Cat' available: expected single matching bean but found 2: cat,cat_c
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'test' defined in class path resource [com/spring/auto/autowire/spring_autowire.xml]: Unsatisfied dependency expressed through bean property 'cat'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.spring.auto.autowire.Cat' available: expected single matching bean but found 2: cat,cat_c
 所以,一旦选择了’byType’类型的自动装配,必须确认配置文件中每个数据类型定义一个唯一的bean。

4、constructor  

使用构造方法完成对象注入,其实也是根据构造方法的参数类型进行对象查找,相当于采用byType的方式。即Spring会寻找与参数数据类型相同的bean,通过构造函数将其注入。

例如:

<bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
    <bean id="dog" class="com.spring.auto.autowire.Dog"></bean>
    <bean id="test" class="com.spring.auto.autowire.Person" autowire="constructor">
        <constructor-arg index="2" value="55"></constructor-arg>
    </bean>

5、default 

表示默认采用上一级标签的自动装配的取值。如果存在多个配置文件的话,那么每一个配置文件的自动装配方式都是独立的。

XML 配置里的 Bean 自动装配的缺点

1、在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性,然而,,若只希望装配个别属性时, autowire 属性就不够灵活了。

2、autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之。

3、一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些。