Spring:基于XML装配bean

目录:

  • 1. 控制反转(IoC)
  • 2. 装配bean
  • 3. 基于XML装配bean
    • 3.1 常规的对象创建方式
    • 3.2 XML装配bean
    • 3.3 依赖注入(DI)
    • 3.4 合并多个XML配置文件
    • 3.5 设置作用域(scope)
  • 4. 参考文档

1. 控制反转(IoC)

IoC(Inversion of Control,控制反转)是Spring框架的核心内容,关于IoC,在Spring的官网中是这样介绍的:


IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.


对于这两段话,个人的理解是:

  • IoC在Spring中通过DI(dependency injection,依赖注入)实现。
  • 在一般的程序中,对象的创建与对象间的依赖关系完全硬编码在程序中,由程序自己控制;所谓IoC,就是指获得依赖对象的方式反转了,对象的创建与依赖关系被交由第三方管理
  • 在Spring中,由Spring IoC容器管理的对象称为bean,即Spring中的bean可以理解为Java中的对象。
  • bean由Spring IoC容器实例化、组装和管理,即前面所提到的对象的创建与依赖关系被交由第三方管理,这对程序的解耦有很大的帮助。
  • 所谓IoC容器,就是指存放bean的地方,当我们有需要时,就可以从中直接取出并使用bean。

2. 装配bean

既然IoC容器是存放bean的地方,那就必然会有一些手段,可以将bean放入容器中。Spring中提供了以下几种bean的装配方式:

  • 基于XML装配bean
  • 利用注解装配bean
  • 使用java配置类装配bean

这里将主要介绍基于XML装配bean的方式。

3. 基于XML装配bean

假设现在由一个包(com.ju.pojo),在包下面有三个类,如下所示:
Spring:基于XML装配bean_第1张图片
每个类的代码如下所示:

package com.ju.pojo;

public class Cat {
    public void shout() { System.out.println("miao~"); }
}
package com.ju.pojo;

public class Dog {
    public void shout() { System.out.println("wang~"); }
}
package com.ju.pojo;

public class Person {
	private String name;
    private Dog dog;
    private Cat cat;

    public Person() {
        this(null, null, null);
    }

    public Person(String name, Dog dog, Cat cat) {
        this.name = name;
        this.dog = dog;
        this.cat = cat;
    }

	public String getName() { return name; }

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

    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; }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", dog=" + dog +
                ", cat=" + cat +
                '}';
    }}

3.1 常规的对象创建方式

接下来创建一个测试类,用于程序的调试,在一般的程序中,测试类似乎应该是这样的:

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        Person person = new Person("ju", dog, cat);
        person.getDog().shout();
        person.getCat().shout();
    }
}

/*
* 运行程序,得到以下结果:
* wang~
* miao~
*/

3.2 XML装配bean

在上面的代码中,对象的创建与依赖关系完全由程序自己控制,这也是大家所熟悉的传统的方式。接下来,我们尝试将控制权交给第三方。

首先,因为是通过XML装配bean,所以需要创建applicationContext.xml文件,并在里面输入以下内容(Spring官网中给出):

<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">

    

beans>

在导入了支持之后,就可以在xml中装配bean了(通俗的说,就是将对象放到Spring IoC容器中),可以通过标签实现bean的装配。


<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">
       
	
    <bean id="dog" class="com.ju.pojo.Dog"/>
    <bean id="cat" class="com.ju.pojo.Cat"/>
    
    
    <alias name="cat" alias="catAlias"/>
    
    
    <bean id="person" class="com.ju.pojo.Person" name="personAlias">
    	
    	<constructor-arg name="name" value="ju"/>
        <constructor-arg name="dog" ref="dog"/>
        <constructor-arg name="cat" ref="cat"/>
    	
		
    	<property name="name" value="ju"/>
        <property name="dog" ref="dog"/>
        <property name="cat" ref="catAlias"/>
    bean>

beans>

至此,bean的配置以及完成,所有的bean都被交由Spring容器管理,当我们需要用到bean的时候,直接从容器中获取即可,即:

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

public class Test {
    public static void main(String[] args) {
        // The ApplicationContext lets you read bean definitions and access them
        // 因为我们是用XML装配的bean,所有要用 ClassPathXmlApplicationContext。
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 从容器中获取bean
        Person person = context.getBean("person", Person.class);
        person.getDog().shout();
        person.getCat().shout();
    }
}

/*
* 运行程序,得到以下结果:
* wang~
* miao~
*/

基于IoC的思想进行编程,我们的程序中不再需要创建对象,也不需要关心对象之间的依赖关系(都被交由Spring容器管理),程序模块间的耦合被大大降低。

通常,在实现一类事物之前,我们会先定义其规范,即先定义接口,这样就可以用同一个接口类型引用不同的实现类。这样做的好处是当我们需要换一种具体实现时,只需在调用时传入一个新的实现类对象即可,无需修改方法的具体实现。

而使用Spring,由于所有的bean被交由Spring容器管理,我们无需修改自己的业务代码,只需要在配置文件中(这里是applicationContext.xml)修改注入的对象即可。

3.3 依赖注入(DI)

在3.2中,给出了两种依赖注入的方式:值注入和引用注入。除此之外,Spring还提供了许多其它的注入方式,以支持如数组、List等类型的注入。

为了更好的说明,这里给出了一个包括大多数Java常用类型的类,用于演示不同类型的XML注入方式:

public class Student {
    private String name;
    private Dog dog;
    private String[] books;
    private List<String> hobbies;
    private Map<Integer, String> cards;
    private Set<String> games;
    private String wife;
    private Properties info;

	// 以下是get、set方法以及一个toString方法,可以不用细看
    public String getName() { return name; }

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

    public Address getAddress() { return address; }

    public void setAddress(Address address) { this.address = address; }

    public String[] getBooks() { return books; }

    public void setBooks(String[] books) { this.books = books; }

    public List<String> getHobbies() { return hobbies; }

    public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }

    public Map<Integer, String> getCards() { return cards; }

    public void setCards(Map<Integer, String> cards) { this.cards = cards; }

    public Set<String> getGames() { return games; }

    public void setGames(Set<String> games) { this.games = games; }

    public String getWife() { return wife; }

    public void setWife(String wife) { this.wife = wife; }

    public Properties getInfo() { return info; }

    public void setInfo(Properties info) { this.info = info; }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbies=" + hobbies +
                ", cards=" + cards +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }
}

各种类型的注入方式与如下:


<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">

     <bean id="dog" class="com.ju.pojo.Dog"/>

    <bean id="student" class="com.ju.pojo.Student">
        
        <property name="name" value=""/>

        
        <property name="dog" ref="dog"/>

        
        <property name="books">
            <array>
                <value>水浒传value>
                <value>三国演义value>
            array>
        property>

        
        <property name="hobbies">
            <list>
                <value>吃饭value>
                <value>睡觉value>
            list>
        property>

        
        <property name="cards">
            <map>
                <entry key="1" value="农行"/>
                <entry key="2" value="交行"/>
            map>
        property>

        
        <property name="games">
            <set>
                <value>LOLvalue>
                <value>CFvalue>
            set>
        property>

        
        <property name="wife">
            <null/>
        property>

        
        <property name="info">
            <props>
                <prop key="driver">nullprop>
                <prop key="url">ju.comprop>
                <prop key="username">Juprop>
                <prop key="password">123456prop>
            props>
        property>
        
    bean>

beans>

3.4 合并多个XML配置文件

利用标签,可以将多个xml配置文件,合并为一个。继续以3.2中的Cat、Dog、Person为例子:

首先为Cat和Dog分别创建了xml配置文件:

  1. cat.xml

<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">
       
    <bean id="cat" class="com.ju.pojo.Cat"/>

beans>
  1. dog.xml

<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">
       
    <bean id="dog" class="com.ju.pojo.Dog"/>

beans>

接下来我们在applicationContext.xml中导入它们,就可以和原来一样装配Person对象了:


<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">
       
    <import resource="cat.xml"/>
    <import resource="dog.xml"/>

    <bean id="person" class="com.ju.pojo.Person" name="personAlias">
        <property name="name" value="ju"/>
        <property name="dog" ref="dog"/>
        <property name="cat" ref="cat"/>
    bean>

beans>

3.5 设置作用域(scope)

通过标签中的scope属性,设置bean的作用域,下表是Spring官网中给出的scope的属性的说明:
Spring:基于XML装配bean_第2张图片
后面的四个属性值,只有在web开发时才会用到,这里主要对前两个进行讲解

  • singleton:(默认)单例模式,即只会有一个bean
    举例:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = context.getBean("person", Person.class);
        Person person1 = context.getBean("person", Person.class);
        // 单例模式下,测试是否是同一个bean
        System.out.println(person == person1); // 结果为true
    }
}
  • protopyte:原型模式,可以有多个bean
    举例:

<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">

    <bean id="dog" class="com.ju.pojo.Dog"/>
    <bean id="cat" class="com.ju.pojo.Cat"/>
    
    
    <bean id="person" class="com.ju.pojo.Person" scope="prototype">
    	<property name="name" value="ju"/>
        <property name="dog" ref="dog"/>
        <property name="cat" ref="cat"/>
    bean>

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

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = context.getBean("person", Person.class);
        Person person1 = context.getBean("person", Person.class);
        // 原型模式下,测试是否是同一个bean
        System.out.println(person == person1); // 结果为false,即得到的不是同一个对象
    }
}

4. 参考文档

官方参考文档:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html

你可能感兴趣的:(Spring入门,java,spring,ioc,bean,intellij,idea)