扫码关注微信公众号

回复“面试手册”,获取本站PDF版

回复“简历”,获取高质量简历模板

回复“加群”,加入程序员交流群

回复“电子书”,获取程序员类电子书

当前位置: Java > Spring高频面试题 > 21.Spring自动装配bean 有哪些方式?

在Spring中实现自动装配的方式有两类,一个是通过XML文件,还有一类是通过注解

通过XML文件

XML文件中的<bean>有一个指定自动装配类型的属性为autowire,autowire有4中装配类型。

  • byName,根据名称自动装配,Spring会将属性名和bean名称进行匹配,如果可以找到就会将bean装配给属性。比如LuRenZhang有一个house属性,而刚好有一个名称为house的bean,则会将bean装配到house属性上
  • byType,根据类型自动装配,Spring会将属性类型和bean类型进行匹配,如果可以找到就会将bean装配给属性。比如LuRenZhang有一个House类型的属性,而刚好有一个类型为House的bean,则会将bean装配到house属性上
  • constructor,Spring容器会尝试找到那些类型与构造函数相匹配的bean,比如LuRenZhang有一个构造函数,构造函数中需要传一个House类型的参数,而刚好有一个类型为House的bean,则会将bean装配到构造函数的参数上
  • autodetect,根据Bean的自省机制决定采用byType还是constructor,首先尝试通过 constructor 来自动装配,如果它不执行,则Spring 尝试通过 byType 来自动装配(spring5.x已经没有了)

举个简单例子,先建两个类,User类,House类

public class House {

    public int getHousePrice() {
        return housePrice;
    }

    public void setHousePrice(int housePrice) {
        this.housePrice = housePrice;
    }

    private int housePrice;


}
public class User {

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setUserAge(int userAge) {
        this.userAge = userAge;
    }


    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    public void setHouse(House house) {
        this.house = house;
    }


    public String getUserName() {
        return userName;
    }

    public int getUserAge() {
        return userAge;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public House getHouse() {
        return house;
    }

    private String userName;
    private int userAge;
    private String userAddress;
    private House house;

    public User() {
    }

    public User(int userId, String userName, int userAge, String userPwd,
                String userAddress, House house) {
        this.userName = userName;
        this.userAge = userAge;
        this.userAddress = userAddress;
        this.house = house;
    }

}

配置XML文件,手动装配bean时

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="house" class="dao.House">
        <property name="housePrice" value="100"/>
    </bean>

    <bean id="user" class="dao.User">
        <!--注入普通值:使用 value 属性-->
        <property name="userName" value="路人张"/>
        <property name="userAge" value="18"/>
        <property name="userAddress" value="北京"/>
        <property name="house" ref="house"/>
    </bean>

</beans>

测试:

class test{
    public static void main(String[] args) {
        //初始化Spring容器ApplicationContext,加载配置文件
        ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user =  application.getBean("user", User.class);
        System.out.println(user.getUserName()+" 房子价值:"+user.getHouse().getHousePrice());

    }
}

结果

路人张 房子价值:100

通过byType自动装配,只需改两行代码,加上autowire="byType",注释或者删掉<property name="house" ref="house"/>

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="house" class="dao.House">
        <property name="housePrice" value="100"/>
    </bean>

    <bean id="user" class="dao.User" autowire="byType">
        <!--注入普通值:使用 value 属性-->
        <property name="userName" value="路人张"/>
        <property name="userAge" value="18"/>
        <property name="userAddress" value="北京"/>
<!--        <property name="house" ref="house"/>-->
    </bean>

</beans>

测试结果还是

路人张 房子价值:100

这时可能有人会问了,如果使用byName或byType时,在XML文件中多个相同名字的bean或者相同类型的bean怎么半,会报异常的。

通过注解

通过注解自动装配bean主要是通过@Autowired等注解完成,前面提到了将类声明为bean的几个注解,还是上面那个例子,如下,通过@Component将类声明为bean,通过@Value这个注解将一些常量值注入到变量中,通过@Autowired将bean装配到属性中

@Component
public class User {


    public String getUserName() {
        return userName;
    }

    public int getUserAge() {
        return userAge;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public House getHouse() {
        return house;
    }

    @Value(value = "路人张")
    private String userName;
    @Value(value = "18")
    private int userAge;
    @Value(value = "北京")
    private String userAddress;
    @Autowired
    private House house;

    public User() {
    }

    public User(int userId, String userName, int userAge, String userPwd,
                String userAddress, House house) {
        this.userName = userName;
        this.userAge = userAge;
        this.userAddress = userAddress;
        this.house = house;
    }

}
@Component
public class House {

    public int getHousePrice() {
        return housePrice;
    }

    @Value(value = "100")
    private int housePrice;


}

测试

class test{
    public static void main(String[] args) {
        //初始化Spring容器ApplicationContext,加载配置文件
        ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user =  application.getBean("user", User.class);
        System.out.println(user.getUserName()+" 房子价值:"+user.getHouse().getHousePrice());

    }
}

输出

路人张 房子价值:100

要想让代码可以正常运行,还需要在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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="dao" />

</beans>

需要注意的是@Autowired:它默认是按byType进行匹配,如果存在多个相同类型的bean,可以使用@Qualifier指定bean的名字,例如@Qualifier(value=”user”)


点击面试手册,获取本站面试手册PDF完整版