Spring使用篇(三)—— Spring中Bean的基本装配方式

本文详细介绍了Spring中Bean的装配方式,包括XML配置和注解装配。首先,阐述了装配Bean的三种方法及其优先级,接着通过实例展示了XML配置装配Bean的全过程,包括装配简易值、集合、命名空间装配。然后,重点讲解了注解装配,如使用@Component、@ComponentScan、@Autowired实现自动装配,并讨论了自动装配的歧义性以及如何通过@Primary和@Qualifier解决。此外,还介绍了使用@Bean进行显示配置以及自定义Bean的初始化和销毁方法。文章旨在帮助读者理解Spring中Bean的装配原理和实践技巧。
摘要由CSDN通过智能技术生成

1、装配Bean概述

  在平时的大部分开发场景中,我们都会使用org.springFramework.context.ApplicationContext的具体实现类,因为对应的Spring IoC容器功能相对强大。而在Spring中提供了3种方法进行配置:

  • 在XML中显式配置
  • 在Java的接口和类中实现配置
  • 隐式Bean的发现机制和自动装配原则

  在显示的开发中,这3中方式都会被用到,并且在学习和工作中常常混合使用,因此需要我们明白这三种方式的优先级,即我们应该如何选择使用哪种方式去把Bean发布到Spring IoC容器中。

  第一,基于“约定优于配置”的原则,最优先的应该是通过隐式Bean的发现机制和自动装配的原则。这样的好处是减少程序开发者的决定权,简单又不失灵活。

  第二,在没有办法使用自动装配原则的情况下应该优先考虑Java接口和类中实现配置,这样的好处是避免XML配置的泛滥,也更为容易。这种场景典型的例子是一个父类有多个子类,比如学生类有两个子类:男生类和女生类,通过IoC容器初始化一个学生类,容器将无法知道使用哪个子类去初始化,这个时候可以使用Java的注解配置去指定。

  第三,在上述方法都无法使用的情况下,那么只能选择XML去配置Spring IoC容器。由于现实开发中常常用到第三方类库,有些类并不是我们开发的,我们无法修改里面的代码,这个时候就通过XML的方式配置使用了。

  通俗来讲,当配置的类时你自身正在开发的工程,那么应该考虑Java配置为主,而Java配置又分为自动装配和Bean名称配置。在没有歧义的基础上,优先使用自动装配,这样就可以减少大量的XML配置。如果所需配置的类并不是你的工程开发的,那么建议使用XML的方式。

2、演示项目环境搭建

  该演示项目开发环境为IDEA,Project名为“Spring Demo”。

  首先,创建名为“BeanAssembling”的Spring Module,具体过程如下:
在这里插入图片描述
  通过该种方式即可在IDEA中快速构建Spring开发环境。然后在lib文件夹中补充导入测试及日志jar包如下:
在这里插入图片描述
  注意,这里采用的Junit的版本与上一篇博客中的版本不一致,该篇博客中使用的是Junit-4.12,之所以没有选择之前的版本,是因为由于之前的版本过低可能会导致在使用Spring上下文测试的时候出现异常,详细信息参考如下博客:

3、通过XML配置装配Bean

  使用XML装配Bean需要定义对应的XML,这里需要引入对应的XML模式(XSD)文件,这些文件会定义配置Spring 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--Spring Bean配置代码-->
</beans>

  在上述配置中引入了一个beans的定义,它是一个根元素,而XSD文件也被引入了,这样它所定义的元素将可以定义对应的Spring Bean。

3.1 装配简易值

  首先,在com.ccff.spring.assembling.pojo包下创建一个Student类,具体代码如下:

package com.ccff.spring.assembling.pojo;

public class Student {
   
    private String name;
    private String sex;
    private String studentNo;
    private Integer age;

    @Override
    public String toString() {
   
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", studentNo='" + studentNo + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public String getSex() {
   
        return sex;
    }

    public void setSex(String sex) {
   
        this.sex = sex;
    }

    public String getStudentNo() {
   
        return studentNo;
    }

    public void setStudentNo(String studentNo) {
   
        this.studentNo = studentNo;
    }

    public Integer getAge() {
   
        return age;
    }

    public void setAge(Integer age) {
   
        this.age = age;
    }
}

  然后在spring-config配置文件中对Student类进行装配,具体配置如下:

<?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">
    <!--Spring Bean配置代码-->
    <!--通过XML配置装配Bean:装配简易值-->
    <bean id="student" class="com.ccff.spring.assembling.pojo.Student">
        <property name="name" value="学生一" />
        <property name="studentNo" value="S001" />
        <property name="age" value="24" />
        <property name="sex" value="" />
    </bean>
</beans>

  其中,id属性时Spring找到的这个Bean的编号,不过id不是一个必需的属性,如果没有声明它,那么Spring将采用“全限定名#{number}”的格式生成编号。如果只声明一个这样的类,而没有声明id=“student”,那么Spring为其生成的编号就是“com.ccff.spring.assembling.pojo.Student#0”。当它第二次声明没有id属性的Bean时,编号就是“com.ccff.spring.assembling.pojo.Student#1”,但是一般我们都会选择自己定义id,因为自动生成的id会比较麻烦。

  class属性显然是一个类全限定名。

  property元素时定义类的属性,其中name属性定义的是属性名称,而value是其值。

  在com.ccff.spring.assembling.test包下创建名为TestStudent的测试类,并在测试类中添加名为“TestEasyAssembingByXML”的测试方法,具体代码如下:

package com.ccff.spring.assembling.test;

import com.ccff.spring.assembling.pojo.Student;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestStudent {
   
    private ApplicationContext context;

    @Before
    public void getContainer(){
   
        context = new ClassPathXmlApplicationContext("spring-config.xml");
    }

    @Test
    public void TestEasyAssembingByXML(){
   
        Student student1 = (Student) context.getBean("student");
        System.out.println(student1);
    }
}

  运行该测试方法后,查看输出到控制台的日志信息如下,则说明Student类的bean已经被创建。
在这里插入图片描述
  这样的定义很简单,但是有时候需要注入一些自定义的类。例如每个学生有属于某一个学校,而学校可以单独抽象出一个类。在com.ccff.spring.assembling.pojo包下创建School类,具体代码如下所示:

package com.ccff.spring.assembling.pojo;

public class School {
   
    private String school_name;
    private String school_no;
    private String school_location;

    public String getSchool_name() {
   
        return school_name;
    }

    public void setSchool_name(String school_name) {
   
        this.school_name = school_name;
    }

    public String getSchool_no() {
   
        return school_no;
    }

    public void setSchool_no(String school_no) {
   
        this.school_no = school_no;
    }

    public String getSchool_location() {
   
        return school_location;
    }

    public void setSchool_location(String school_location) {
   
        this.school_location = school_location;
    }

	@Override
    public String toString() {
   
        return "School{" +
                "school_name='" + school_name + '\'' +
                ", school_no='" + school_no + '\'' +
                ", school_location='" + school_location + '\'' +
                '}';
    }
}

  然后,修改Student类,为其指定所属的学校,具体代码如下:

package com.ccff.spring.assembling.pojo;

public class Student {
   
    private String name;
    private String sex;
    private String studentNo;
    private Integer age;
    private School school;

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public String getSex() {
   
        return sex;
    }

    public void setSex(String sex) {
   
        this.sex = sex;
    }

    public String getStudentNo() {
   
        return studentNo;
    }

    public void setStudentNo(String studentNo) {
   
        this.studentNo = studentNo;
    }

    public Integer getAge() {
   
        return age;
    }

    public void setAge(Integer age) {
   
        this.age = age;
    }

    public School getSchool() {
   
        return school;
    }

    public void setSchool(School school) {
   
        this.school = school;
    }
    
    @Override
    public String toString() {
   
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", studentNo='" + studentNo + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

  由于增加了School类,因此需要在spring-config中先配置School类Bean。然后在配置的school bean中增加School类型的属性的配置,具体配置如下:

<?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">
    <!--Spring Bean配置代码-->
    <!--通过XML配置装配Bean:装配简易值-->
    <bean id="school" class="com.ccff.spring.assembling.pojo.School">
        <property name="school_name" value="中国科学院大学" />
        <property name="school_no" value="Sch001" />
        <property name="school_location" value="北京市怀柔区怀北镇怀北庄中国科学院大学雁西湖校区" />
    </bean>
    <bean id="student" class="com.ccff.spring.assembling.pojo.Student">
        <property name="name" value="学生一" />
        <property name="studentNo" value="S001" />
        <property name="age" value="24" />
        <property name="sex" value="" />
        <property name="school" ref="school" />
    </bean>
</beans>

  修改测试方法TestEasyAssembingByXML如下:

package com.ccff.spring.assembling.test;

import com.ccff.spring.assembling.pojo.School;
import com.ccff.spring.assembling.pojo.Student;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestStudent {
   
    private ApplicationContext context;

    @Before
    public void getContainer(){
   
        context = new ClassPathXmlApplicationContext("spring-config.xml");
    }

    @Test
    public void TestEasyAssembingByXML(){
   
        School school = (School) context.getBean("school");
        System.out.println(school);
        Student student1 = (Student) context.getBean("student");
        System.out.println(student1);
    }
}

  这里先定义了一个id为school的Bean,然后在id为student的Bean中使用ref属性引用对应的Bean,而school正是之前创建的school的id,这样就可以相互引用了。

  运行该测试方法后,查看输出到控制台的日志信息如下,则说明Student类的bean已经被创建。
在这里插入图片描述

3.2 装配集合

  有些时候需要做一些复杂的装配工作,比如Set、Map、List、Array和Properties等。为了演示这些复杂的装配工作,首先在com.ccff.spring.assembling.pojo包中定义名为“ComplexAssembly”的类,具体代码如下:

package com.ccff.spring.assembling.pojo;

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

public class ComplexAssembly {
   
    private Long id;
    private List<String> list;
    private Map<String,String> map;
    private Properties properties;
    private Set<String> set;
    private String[] array;

    public Long getId() {
   
        return id;
    }

    public void setId(Long id) {
   
        this.id = id;
    }

    public List<String> getList() {
   
        return list;
    }

    public void setList(List<String> list) {
   
        this.list = list;
    }

    public Map<String, String> getMap() {
   
        return map;
    }

    public void setMap(Map<String, String> map) {
   
        this.map = map;
    }

    public Properties getProperties() {
   
        return properties;
    }

    public void setProperties(Properties properties) {
   
        this.properties = properties;
    }

    public Set<String> getSet() {
   
        return set;
    }

    public void setSet(Set<String> set) {
   
        this.set = set;
    }

    public String[] getArray() {
   
        return array;
    }

    public void setArray(String[] array) {
   
        this.array = array;
    }
}

  接下来在spring-config中完成这些复杂的装配工作,具体代码如下所示:

<?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">
    <!--Spring Bean配置代码-->
    <!--通过XML配置装配Bean:装配简易值-->
    <bean id="school" class="com.ccff.spring.assembling.pojo.School">
        <property name="school_name" value="中国科学院大学" />
        <property name="school_no" value="Sch001" />
        <property name="school_location" value="北京市怀柔区怀北镇怀北庄中国科学院大学雁西湖校区" />
    </bean>
    <bean id="student" class="com.ccff.spring.assembling.pojo.Student">
        <property name="name" value="学生一" />
        <property name="studentNo" value="S001" />
        <property name="age" value="24" />
        <property name="sex" value="" />
        <property name="school" ref="school" />
    </bean>

    <!--通过XML配置装配Bean:装配集合-->
    <bean id="complexAssembly" class="com.ccff.spring.assembling.pojo.ComplexAssembly">
        <property name="id" value="1" />
        <property name="list">
            <</
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值