SpringBean自动装配

开课吧开课吧锤锤2021-08-09 11:46

Bean的装配可以理解为依赖关系注入,Bean的装配方式也就是Bean的依赖注入方式。Spring容器支持多种装配Bean的方式,如基于XML的Bean装配、基于Annotation的Bean装配和自动装配等。  

Spring基于XML的装配通常采用两种实现方式,即我们在《Spring依赖注入》一节介绍的setter注入和构造注入。本节介绍如何配置自动装配。  

自动装配就是指Spring容器在不使用<constructor-arg>和<property>标签的情况下,可以自动装配(autowire)相互协作的Bean之间的关联关系,将一个Bean注入其他Bean的Property中。  

使用自动装配需要配置<bean>元素的autowire属性。autowire属性有五个值,具体说明如下表所示。  

autowire的属性和作用  

 
名称 说明
no 默认值,表示不使用自动装配,Bean 依赖必须通过 ref 元素定义。
byName 根据 Property 的 name 自动装配,如果一个 Bean 的 name 和另一个 Bean 中的 Property 的 name 相同,则自动装配这个 Bean 到 Property 中。
byType 根据 Property 的数据类型(Type)自动装配,如果一个 Bean 的数据类型兼容另一个 Bean 中 Property 的数据类型,则自动装配。
constructor 类似于 byType,根据构造方法参数的数据类型,进行 byType 模式的自动装配。
autodetect(3.0版本不支持) 如果 Bean 中有默认的构造方法,则用 constructor 模式,否则用 byType 模式。

示例  

下面使用EclipseIDE演示SpringBean的自动装配,步骤如下:  

1、创建SpringDemo项目,并在src目录下创建net.kaikeba包。  

2、添加相应的jar包.  

3、在net.kaikeba包下创建Person、Man和MainApp类。  

4、在src目录下创建Spring配置文件Beans.xml。  

5、运行SpringDemo项目。  

Person类代码如下。  

package net.kaikeba;
public class Person {
    private Man man;
    public Person(Man man) {
        System.out.println("在Person的构造函数内");
        this.man = man;
    }
    public void man() {
        man.show();
    }
}

Man类代码如下。 

package net.kaikeba;
public class Man {
    private String name;
    private int age;
    public Man() {
        System.out.println("在man的构造函数内");
    }
    public Man(String name, int age) {
        System.out.println("在man的有参构造函数内");
        this.name = name;
        this.age = age;
    }
    public void show() {
        System.out.println("名称:" + name + "\n年龄:" + age);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

MainApp类代码如下。 

package net.kaikeba;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        Person person = (Person) context.getBean("person");
        person.man();
    }
}

1)不使用自动装配(autowire="no")  

autowire="no"表示不使用自动装配,需要手动注入,Bean依赖通过ref元素定义,Beans.xml配置文件如下。  

<?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-3.0.xsd">
    <bean id="man" class="net.kaikeba.Man">
        <constructor-arg value="kaikeba" />
        <constructor-arg value="8" type="int" />
    </bean>
    <bean id="person" class="net.kaikeba.Person" autowire="no">
        <constructor-arg ref="man" type="java.lang.String"/>
    </bean>
</beans>

2)按名称自动装配(autowire="byName")  

autowire="byName"表示按属性名称自动装配,XML文件中Bean的id必须与类中的属性名称相同。配置文件内容修改如下。  

<bean id="man" class="net.kaikeba.Man">
    <constructor-arg value="kaikeba" />
    <constructor-arg value="8" type="int" />
</bean>
<bean id="person" class="net.kaikeba.Person" autowire="byName"/>

运行结果如下。  

在man的有参构造函数内
在Person的构造函数内
名称:kaikeba
年龄:8

如果更改Bean的名称,很可能不会注入依赖项。  

将Bean的名称更改为man1,配置文件如下:  

<bean id="man1" class="net.kaikeba.Man">
    <constructor-arg value="kaikeba" />
    <constructor-arg value="12" type="int" />
</bean>
<bean id="person" class="net.kaikeba.Person" autowire="byName"/>

注入失败,异常信息为:  

在man的有参构造函数内
Exception in thread "main" java.lang.NullPointerException
at net.kaikeba.Person.man(Person.java:16)
at net.kaikeba.MainApp.main(MainApp.java:10)

3)按类型自动装配(autowire="byType")  

XML文件中Bean的id与类中的属性名称可以不同,但必须只有一个类型的Bean。配置文件内容修改如下。  

<bean id="man1" class="net.kaikeba.Man">
    <constructor-arg value="kaikeba" />
    <constructor-arg value="8" type="int" />
</bean>
<bean id="person" class="net.kaikeba.Person" autowire="byType"/>

运行结果如下。

在man的有参构造函数内
在Person的构造函数内
名称:kaikeba
年龄:8

如果您有相同类型的多个Bean,则注入失败,并且引发异常。  

添加id为man2的Bean,配置文件代码如下。  

<bean id="man1" class="net.kaikeba.Man">
  <constructor-arg value="kaikeba" />
  <constructor-arg value="8" type="int" />
</bean>
<bean id="man2" class="net.kaikeba.Man">
  <constructor-arg value="kaikeba" />
  <constructor-arg value="8" type="int" />
</bean>
<bean id="person" class="net.kaikeba.Person" autowire="byType"/>

异常信息为:  

在man的有参构造函数内
在man的有参构造函数内
一月 26, 2021 1:34:14 下午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person' defined in class path resource [Beans.xml]: Unsatisfied dependency expressed through bean property 'man'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'net.kaikeba.Man' available: expected single matching bean but found 2: man1,man2
...

4)构造函数自动装配(autowire="constructor")  

修改Person类的代码。  

package net.kaikeba;
public class Person {
    private Man man;
    public Person(Man man) {
        System.out.println("在Person的构造方法内");
        this.man = man;
    }
    public Man getMan() {
        return man;
    }
    public void man() {
        man.show();
    }
}

类中构造函数的参数必须在配置文件中有相同的类型,配置文件内容修改如下。  

<bean id="man" class="net.kaikeba.Man">
    <constructor-arg value="kaikeba" />
    <constructor-arg value="8" type="int" />
</bean>
<bean id="person" class="net.kaikeba.Person" autowire="constructor"/>

运行结果如下。  

在man的有参构造函数内
在Person的构造函数内
名称:kaikeba
年龄:8

自动装配的优缺点  

优点  

自动装配只需要较少的代码就可以实现依赖注入。  

缺点  

不能自动装配简单数据类型,比如int、boolean、String等。  

相比较显示装配,自动装配不受程序员控制。  

以上就是开课吧广场小编为大家整理发布的“SpringBean自动装配”一文,更多Java教程相关内容尽在开课吧广场Java教程频道!  

开课吧广场Java教程

免责声明:本站所提供的内容均来源于网友提供或网络搜集,由本站编辑整理,仅供个人研究、交流学习使用。如涉及版权问题,请联系本站管理员予以更改或删除。
有用
分享