首页 > 代码库 > 7 -- Spring的基本用法 -- 7...

7 -- Spring的基本用法 -- 7...

    7.7 创建Bean的3种方式

      ① 调用构造器创建Bean。

      ② 调用静态工厂方法创建Bean。

      ③ 调用实例工厂方法创建Bean。

      7.7.1 使用构造器创建Bean实例。

        使用构造器来创建Bean实例是最常见的情况,如果不采用构造注入,Spring底层会调用Bean类的无参数构造器来创建实例,因此要求该Bean类提供无参数的构造器。在这种情况下,class元素是必须的(除非采用继承),class属性的值就是Bean实例的实现类。

        如果不采用构造注入,Spring容器将使用默认的构造器来创建Bean实例,SPring对Bean实例的所有属性执行默认初始化,即所有基本类型的值初始化为0或false;所有引用类型的值初始化为null。然后BeanFactory会根据配置文件决定依赖关系,先实例化被依赖的Bean实例,然后为Bean注入依赖关系,最后将一个完整的Bean实例返回给程序。

        如果采用构造注入,则要求配置文件为<bean.../>元素添加<constructor-arg.../>子元素,每个<constructor-arg.../>子元素配置一个构造器参数。Spring容器将使用带对应参数的构造器来创建Bean实例,Spring调用构造器传入的参数即可用于初始化Bean的实例变量,最后也将一个完整的Bean实例返回给程序。

      7.7.2 使用静态工厂方法创建Bean

        使用静态工厂方法创建Bean实例时,class属性也必须指定,但此时class属性并不是指定Bean实例的实现类,而是静态工厂类,Spring通过该属性知道由那个工厂类来创建Bean实例。

        除此之外,还需要使用factory-method属性来指定静态工厂方法,Spring将调用静态工厂方法(可能包含一组参数)返回一个Bean实例,一旦获得指定Bean实例,Spring后面的处理步骤与采用普通方法创建Bean实例则完全一样。

        <bean.../>元素的class属性指定的是静态工厂类,factory-method指定的工厂方法必须是静态的。

        采用静态工厂方法创建Bean实例时,<bean.../>元素需要指定如下两个属性:

        ⒈ class : 该属性的值为静态工厂类的类名。

        ⒉ factory-method : 该属性指定静态工厂方法来生产Bean实例。

        如果静态工厂方法需要参数,则使用<constructor-arg.../>元素传入。 

        Interface : Being

package edu.pri.lime._7_7_2.bean;

public interface Being {
    public void testBeing();
}

        Class : Dog

package edu.pri.lime._7_7_2.bean.impl;

import edu.pri.lime._7_7_2.bean.Being;

public class Dog implements Being{

    private String msg;
    public void testBeing() {
        System.out.println(msg + ",狗爱肯骨头");
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }

}

        Class : Cat

package edu.pri.lime._7_7_2.bean.impl;

import edu.pri.lime._7_7_2.bean.Being;

public class Cat implements Being {

    private String msg;
    
    public void testBeing() {
        System.out.println(msg + ",猫喜欢吃老鼠");
    }

    public String getMsg() {
        return msg;
    }
    
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

        Class : BeanFactory

package edu.pri.lime._7_7_2.bean.factory;

import edu.pri.lime._7_7_2.bean.Being;
import edu.pri.lime._7_7_2.bean.impl.Cat;
import edu.pri.lime._7_7_2.bean.impl.Dog;

public class BeingFactory {
//    返回Being实例的静态工厂方法
//    arg参数决定返回那个Being类的实例
    public static Being getBeing(String arg){
//        调用此静态方法的参数为dog,则返回Dog实例
        if(arg.equalsIgnoreCase("dog")){
            return new Dog();
        }else{
//            否则放回Cat实例
            return new Cat();
        }
    }
}

        XML : 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <!-- 驱动Spring调用BeingFactory的静态getBeing()方法来创建Bean,该bean元素包含的constructor-arg元素用于为静态工厂方法指定参数 -->
    <bean id="dog" class="edu.pri.lime._7_7_2.bean.factory.BeingFactory"
        factory-method="getBeing">
        <!-- 配置静态工厂方法的参数 -->
        <constructor-arg value="dog" />
        <!-- 驱动Spring以“你才是狗”为参数来执行dog的setMsg()方法 -->
        <property name="msg" value="你才是狗"/>
    </bean>
    <bean id="cat" class="edu.pri.lime._7_7_2.bean.factory.BeingFactory" factory-method="getBeing">
        <constructor-arg value="cat"/>
        <property name="msg" value="你全家都是猫"/>
    </bean>
</beans>

        Class : SpringTest

package edu.pri.lime._7_7_2.main;

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

import edu.pri.lime._7_7_2.bean.Being;
import edu.pri.lime._7_7_2.bean.impl.Cat;
import edu.pri.lime._7_7_2.bean.impl.Dog;

public class SpringTest {
    public static void main(String[] args){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_7_2.xml");
        Being dog = ctx.getBean("dog",Dog.class);
        Being cat = ctx.getBean("cat",Cat.class);
        dog.testBeing();
        cat.testBeing();
    }
}

        一旦为<bean.../>元素指定了factory-method属性,Spring就不再调用构造器来创建Bean实例,而是调用工厂方法来创建Bean实例。

        如果同时指定了class 和 factory-method 两个属性,Spring就会调用静态工厂方法来创建Bean。

        ┠ class属性的值不再是Bean实例的实现类,而是生成Bean实例的静态工厂类。

        ┠ 使用factory-method 属性指定创建Bean实例的静态工厂方法。

        ┠ 如果静态工厂方法需要参数,则使用<constructor-arg.../>元素指定静态工厂方法的参数。

        使用静态工厂方法创建Bean实例的过程中,Spring不在负责创建Bean实例,Bean实例是由用户提供的静态工厂类负责创建的。当静态工厂方法创建了Bean实例后,Spring依然可以管理该Bean实例的依赖关系,包括为其注入所需的依赖Bean、管理其生命周期等。

7 -- Spring的基本用法 -- 7...