zoukankan      html  css  js  c++  java
  • 7 -- Spring的基本用法 -- 7... 创建Bean的3种方式

        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 {

        public BeingFactory() {
           super();
           System.out.println("实例化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.7.3 调用实例工厂方法创建Bean

            区别:调用静态工厂方法只需使用工厂类即可,而调用实例工厂方法则需要工厂实例;配置静态工厂方法使用class指定静态工厂类,而配置实例工厂方法则使用factory-bean指定工厂实例。

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

              ① factory-bean : 该属性的值为工厂Bean的id。

              ② factory-method : 该属性指定实例工厂的工厂方法。

              <constructor-arg.../>元素使在调用实例工厂方法时可以传入参数。

            Interface : Person

    package edu.pri.lime._7_7_3.bean;
    
    public interface Person {
    
        public String sayHello(String name);
        public String sayGoodBye(String name);
    }

            Class : Chinese

    package edu.pri.lime._7_7_3.bean.impl;
    
    import edu.pri.lime._7_7_3.bean.Person;
    
    public class Chinese implements Person {
    
        public String sayHello(String name) {
            return name + ",您好!";
        }
    
        public String sayGoodBye(String name) {
            return name + ",下次再见!";
        }
    
    }

            Class : American

    package edu.pri.lime._7_7_3.bean.impl;
    
    import edu.pri.lime._7_7_3.bean.Person;
    
    public class American implements Person {
    
        public String sayHello(String name) {
            return name + ",Hello!";
        }
    
        public String sayGoodBye(String name) {
            return name + ",Good Bye!";
        }
    
    }

            Class : PersonFactory

    package edu.pri.lime._7_7_3.beanfactory;
    
    import edu.pri.lime._7_7_3.bean.Person;
    import edu.pri.lime._7_7_3.bean.impl.American;
    import edu.pri.lime._7_7_3.bean.impl.Chinese;
    
    //负责生产Person对象的实例工厂
    public class PersonFactory {

         public PersonFactory() {
              super();
              System.out.println("实例化PersonFactory");
          }

    //    获得Person实例的实例工厂方法
    //    ethnic参数决定返回那个Person实现类的实例
    //    没有使用Static修饰,因此这只是一个实例工厂方法
        public Person getPerson(String ethnic){
            if(ethnic.equalsIgnoreCase("chin")){
                return new Chinese();
            }else{
                return new American();
            }
        }
    }

            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">
        <!-- 配置工厂Bean,该Bean负责产生其他Bean实例 -->
        <bean id="personFactory" class="edu.pri.lime._7_7_3.beanfactory.PersonFactory" />
        <!-- 
            驱动Spring调用personFactory Bean的getPerson()方法来创建Bean, 
            该bean元素包含的constructor-arg元素用于为工厂方法指定参数, 
            因此这段配置会驱动Spring以反射方式来执行如下代码: 
            PersonFactory pf = container.get("personFactory"); 
            chinese = pf.getPerson("chin");
             -->
        <bean id="chinese" factory-bean="personFactory" factory-method="getPerson">
            <!-- 配置实例工厂方法的参数 -->
            <constructor-arg value="chin" />
        </bean>
        <!-- 
        驱动Spring以反射方式来执行如下代码:
        PersonFactory pf = container.get("personFactory");
        american = pf.getPerson("ame");
         -->
        <bean id="american" factory-bean="personFactory" factory-method="getPerson">
            <constructor-arg value="ame" />
        </bean>
    
    </beans>

            Class : SpringTest

    package edu.pri.lime._7_7_3.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import edu.pri.lime._7_7_3.bean.Person;
    import edu.pri.lime._7_7_3.bean.impl.American;
    import edu.pri.lime._7_7_3.bean.impl.Chinese;
    
    public class SpringTest {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_7_3.xml");
            Person chinese = ctx.getBean("chinese", Chinese.class);
            System.out.println(chinese.sayHello("lime"));
            System.out.println(chinese.sayGoodBye("lime"));
            
            Person american = ctx.getBean("american",American.class);
            System.out.println(american.sayHello("oracle"));
            System.out.println(american.sayGoodBye("oracle"));
        }
    }

            区别:

              配置实例工厂方法创建Bean,必须将实例工厂配置成Bean实例;而配置静态工厂方法创建Bean,则无须配置工厂Bean。

              配置实例工厂方法创建Bean,必须使用factory-bean属性确定工厂Bean;而配置静态工厂方法创建Bean,则使用class元素确定静态工厂类。

            相同:

              都需要使用factory-method 属性指定生产Bean实例的方法。

              工厂方法如果需要参数,都使用<constructor-arg.../>元素指定参数值。

              普通的设置注入,都使用<property.../>元素确定参数值。

  • 相关阅读:
    【JS】修改字体
    【git】.gitignore文件常用设置
    【CSS】让textarea在div里水平垂直都居中的三种办法
    【JS】随着进度条进展,逐个显示li节点
    【MySQL】The server time zone value 'xxxxxx' is unrecognized or represents more than one time zone 解决方案
    浅谈Web前端开发中的Touch事件
    [转]PostgreSQL与MySQL比较
    RDLC:An error occurred during local report processing
    [转]让你的PHP更安全
    [转]Win7或Windows server 2008中IIS7支持ASP+Access解决方法
  • 原文地址:https://www.cnblogs.com/ClassNotFoundException/p/6260680.html
Copyright © 2011-2022 走看看