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.../>元素确定参数值。

7 -- Spring的基本用法 -- 7... 创建Bean的3种方式的更多相关文章

  1. spring创建bean的三种方式

    spring创建bean的三种方式: 1通过构造方法创建bean(最常用) 1.1 spring默认会通过无参构造方法来创建bean,如果xml文件是这样配置,则实体类中必须要有无参构造方法,无参构造 ...

  2. Spring 创建Bean的6种方式

    前言 本文讲解了在Spring 应用中创建Bean的多种方式,包括自动创建,以及手动创建注入方式,实际开发中可以根据业务场景选择合适的方案. 方式1: 使用Spring XML方式配置,该方式用于在纯 ...

  3. spring-第六篇之创建bean的3种方式

    1.创建bean的方式有3种: 1>使用构造器创建bean,即设值注入.构造注入本质都是使用bean的构造器创建bean的. 2>使用静态工厂方法创建bean. 3>调用实例工厂方法 ...

  4. Spring学习之实例化bean的三种方式

    实例化bean的三种方式 构造器实例化bean Person.java public class Person { private String name; private Integer age; ...

  5. Spring创建JobDetail的两种方式

    一.Spring创建JobDetail的两种方式 二.整合方式一示例步骤 1.将spring核心jar包.quartz.jar和Spring-context-support.jar导入类路径. 2.编 ...

  6. Spring实战(三)Spring中装配Bean的三种方式---XML、JavaConfig、AutoWire

    创建应用对象之间协作关系的行为称为装配(wiring),这也是依赖注入的本质. Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,而开发者需要告诉Spring需要创建哪些 ...

  7. spring装配bean的三种方式及其混合装配

    在spring容器中装配bean有三种基本方式和混合装配方式: 隐式的bean自动发现机制和自动装配 在java中进行显式配置 在xml中配置 混合装配(在多个java文件中配置.在JavaConfi ...

  8. Spring定义Bean的两种方式:和@Bean

    前言:    Spring中最重要的概念IOC和AOP,实际围绕的就是Bean的生成与使用. 什么叫做Bean呢?我们可以理解成对象,每一个你想交给Spring去托管的对象都可以称之为Bean. 今天 ...

  9. spring 注入bean的两种方式

    我们都知道,使用spring框架时,不用再使用new来实例化对象了,直接可以通过spring容器来注入即可. 而注入bean有两种方式: 一种是通过XML来配置的,分别有属性注入.构造函数注入和工厂方 ...

随机推荐

  1. linux 网络安全不完全笔记

    一.安装Centos二.Linux网络网络环境设置 a.配置linux与客户机相连通 b.配置linux上网三.Yum详解 yum 的基本操作 a.使用 yum 安装新软件 yum install – ...

  2. [Python学习]Python学习资料汇总

    Python其实很简单,入门+提高看一些简单的教程就能学会,这里列出一些比较好的资料: 廖雪峰博客 https://www.liaoxuefeng.com/wiki/0014316089557264a ...

  3. kafka中的消费组

    一直以来都想写一点关于kafka consumer的东西,特别是关于新版consumer的中文资料很少.最近Kafka社区邮件组已经在讨论是否应该正式使用新版本consumer替换老版本,笔者也觉得时 ...

  4. 微信小程序——页面中调用组件方法

    我现在有一个弹层的组件(popup),组件里面定义了显示组件(showPopup)和隐藏组件(hidePopup)的方法. 我们如何在调用组件的页面中调用组件里面的方法呢? 在调用组件的页面写如下代码 ...

  5. 从Java开发者的视角解释JavaScript

    我们无法在一篇博文里解释JavaScript的所有细节.如果你正或多或少地涉及了web应用程序开发,那么,我们的Java工具和技术范围报告揭示了,大多数(71%)Java开发者被归到了这一类,只是你对 ...

  6. Enums and Lookup Tables with EF Code First

    With EntityFramework’s support for enums, there is no longer any need to include lookup tables in th ...

  7. 关于Unity中蒙皮网格和布料的使用

    所以物体的要绘制出来就必须要有网格组件+材质属性,如果还需要其他特效或丰富内容的话,还可以再加组件. 蒙皮网格和布料 1: 例如要模拟衣服,随风摆动,模拟布料需要用到蒙皮网格和布料;2: 蒙皮网格可以 ...

  8. 读《像计算机科学家一样思考python》——笔记

    这本书,完全是入门级的,特别简单,一天多就看完. 目录: 第二章 变量.表达式和语句 第三章: 函数调用 第四章: 案例研究:接口设计 第五章 条件与递归 第六章:有返回值的函数 第七章 迭代 第八章 ...

  9. 将项目安装到Maven本地资源库

    在Maven中,可以使用“mvn install”打包项目,并自动部署到本地资源库,让其他开发人员使用它. mvn install 注意,当“install”在执行阶段,上述所有阶段 “validat ...

  10. C# 窗体间传值(使用委托与自定义事件)

    using System; using System.Drawing; using System.Windows.Forms; namespace 跨窗体调用控件 { public partial c ...