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...的更多相关文章

  1. SpringMVC +mybatis+spring 结合easyui用法及常见问题总结

    SpringMVC +mybatis+spring 结合easyui用法及常见问题总结 1.FormatString的用法. 2.用postAjaxFillGrid实现dataGrid 把form表单 ...

  2. Spring中@Async用法详解及简单实例

    Spring中@Async用法 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类 ...

  3. (转)Spring中@Async用法总结

     原文:http://blog.csdn.net/blueheart20/article/details/44648667 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的: ...

  4. Spring中@Async用法总结

    引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3. ...

  5. spring AOP的用法

    AOP,面向切面编程,它能把与核心业务逻辑无关的散落在各处并且重复的代码给封装起来,降低了模块之间的耦合度,便于维护.具体的应用场景有:日志,权限和事务管理这些方面.可以通过一张图来理解下: Spri ...

  6. Spring常用注解用法总结

    转自http://www.cnblogs.com/leskang/p/5445698.html 1.@Controller 在SpringMVC 中,控制器Controller 负责处理由Dispat ...

  7. Spring中@Value用法收集

    一.配置方式 @Value需要参数,这里参数可以是两种形式: @Value("#{configProperties['t1.msgname']}") 或者 @Value(" ...

  8. Spring data redis-StringRedisTemplate 用法

    Spring-data-redis为spring-data模块中对redis的支持部分,简称为“SDR”,提供了基于jedis客户端API的高度封装以及与spring容器的整合,事实上jedis客户端 ...

  9. Spring.Net简单用法

    Spring.Net其实就是抽象工厂,只不过更加灵活强大,性能上并没有明显的区别. 它帮我们实现了控制反转. 其有两种依赖注入方式. 第一:属性注入 第二:构造函数注入 首先,我们去  Spring. ...

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

    7.6 Spring 3.0 提供的Java配置管理 Spring 允许使用Java类进行配置管理,可以不使用XML来管理Bean,以及Bean之间的依赖关系. Interface :Person p ...

随机推荐

  1. 如何获取网页上的LOGO

    一般公司网页上的图片都会禁止右键另存为,用截图工具接下来的图会带背景色,PS成背景透明有点费时间. 用Google Chrome 或Firefox 打开目标网页,右键点击审查元素,将鼠标放在图片上,一 ...

  2. WindowsFormsIntegration.dll

    WindowsFormsIntegration.dll的位置如下 C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFrame ...

  3. Apache Benchmark测试工具

    ab命令-- ab -c 数字(连接数) -t 数字(连接时间) http://网站:端口/路径 ab -n 数字(点击数) -c 数字(连接数) -k(同时点击) http://网站:端口/路径

  4. [CC]Plugin-提取ISS3D关键点

    基于CloudCompare开发的提取ISS3D关键点. void qLxPluginPCL::doISS3D() { assert(m_app); if (!m_app) return; const ...

  5. VS 解决方案管理器和 编辑窗口同步 联动

    对于题目的解释就是   当我点击一下解决方案管理器中的 某一个文档时, 编辑窗口会联动的   同步到对应的窗口。之前好像被我无意中关掉了,今天重新建立一个项目无意中发现怎么设置了 如果想点击右边的文档 ...

  6. AppleWatch___学习笔记(一)开发思路和框架

    一.开发须知 如果你没有开发过 iphone,直接来做watch,我建议你不要这么做,不是不可以,而是目前所有的第三方应用都必须基于iphone的扩展,原生的watch应用,苹果目前还没有开放给开发者 ...

  7. python-判断系统平台

    1.windows 2.linux 总结 python提供了sys,os及platform等个模块读取平台信息,客官可以根据自己的喜好选择使用

  8. jquery幻灯片

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  9. Android中插件开发篇之----动态加载Activity(免安装运行程序)

    一.前言 又到周末了,时间过的很快,今天我们来看一下Android中插件开发篇的最后一篇文章的内容:动态加载Activity(免安装运行程序),在上一篇文章中说道了,如何动态加载资源(应用换肤原理解析 ...

  10. 简单的计算最值的MapReduce程序

    import java.io.IOException;import java.util.StringTokenizer;import java.util.*;import org.apache.had ...