Spring 通过工厂方法(Factory Method)来配置bean

在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean.

在第一种利用bean config file(spring xml)方式中, 还包括如下三小类

  1. 反射模式

  2. 工厂方法模式(本文重点)

  3. Factory Bean模式

其中反射模式最常见, 我们需要在bean 配置中指明我们需要的bean object的全类名。

例如:

<bean id="car1" class="com.home.factoryMethod.Car">
<property name="id" value="1"></property>
<property name="name" value="Honda"></property>
<property name="price" value="300000"></property>
</bean>

上面bean 里面的class属性就是全类名, Spring利用java反射机制创建这个bean。

Factory方法模式

本文介绍的是另1种模式, 在工厂方法模式中, Spring不会直接利用反射机制创建bean对象, 而是会利用反射机制先找到Factory类,然后利用Factory再去生成bean对象。

而Factory Mothod方式也分两种, 分别是静态工厂方法 和 实例工厂方法。

静态工厂方法方式

所谓镜头静态工厂方式就是指Factory类不本身不需要实例化, 这个Factory类中提供了1个静态方法来生成bean对象

下面是例子

bean类Car

首先我们定义1个bean类Car

package com.home.factoryMethod;

public class Car {
private int id;
private String name;
private int price; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getPrice() {
return price;
} public void setPrice(int price) {
this.price = price;
} @Override
public String toString() {
return "Car [id=" + id + ", name=" + name + ", price=" + price + "]";
} public Car(){ } public Car(int id, String name, int price) {
super();
this.id = id;
this.name = name;
this.price = price;
}
}

然后我们再定义1个工厂类CarStaticFactory

package com.home.factoryMethod;

import java.util.HashMap;
import java.util.Map; public class CarStaticFactory {
private static Map<Integer, Car> map = new HashMap<Integer,Car>(); static{
map.put(1, new Car(1,"Honda",300000));
map.put(2, new Car(2,"Audi",440000));
map.put(3, new Car(3,"BMW",540000));
} public static Car getCar(int id){
return map.get(id);
}
}

里面定义了1个静态的bean 容器map. 然后提供1个静态方法根据Car 的id 来获取容器里的car对象。

xml配置

  <!--
Static Factory method:
class: the class of Factory
factory-method: method of get Bean Object
constructor-arg: parameters of factory-method
-->
<bean id="bmwCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
<constructor-arg value="3"></constructor-arg>
</bean> <bean id="audiCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
<constructor-arg value="2"></constructor-arg>
</bean>

可以见到, 利用静态工厂方法定义的bean item种, class属性不在是bean的全类名, 而是静态工厂的全类名, 而且还需要指定工厂里的

getBean 静态方法名字和参数

客户端代码

public static void h(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factoryMethod.xml");
Car car1 = (Car) ctx.getBean("bmwCar");
System.out.println(car1); car1 = (Car) ctx.getBean("audiCar");
System.out.println(car1);
}

输出

May 30, 2016 11:17:45 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@43765ab3: startup date [Mon May 30 23:17:45 CST 2016]; root of context hierarchy
May 30, 2016 11:17:46 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [bean-factoryMethod.xml]
Car [id=3, name=BMW, price=540000]
Car [id=2, name=Audi, price=440000]

小结

由上面的例子, 静态工厂方法方式是非常适用于作为1个bean容器(集合的), 只不过吧bean集合定义在工厂类里面而不是bean config file里面。 
缺点也比较明显, 把数据写在class里面而不是配置文件中违反了我们程序猿的常识和spring的初衷。当然优点就是令到令人恶心的bean config file更加简洁啦。

实例工厂方法方式

所谓实例工厂方式也很容易看懂, 就是里面的getBean 方法不是静态的, 也就是代表要先实例1个工厂对象, 才能依靠这个工厂对象去获得bean 对象。

用回上面的例子。

而这次我们写1个实例工厂类

CarInstanceFactroy

package com.home.factoryMethod;

import java.util.HashMap;
import java.util.Map; public class CarInstanceFactory {
private Map<Integer, Car> map = new HashMap<Integer,Car>(); public void setMap(Map<Integer, Car> map) {
this.map = map;
} public CarInstanceFactory(){
} public Car getCar(int id){
return map.get(id);
}
}

bean xml写法

<!-- Instance Factory Method:
1.must create a bean for the Instance Factroy First
-->
<bean id="carFactory" class="com.home.factoryMethod.CarInstanceFactory">
<property name="map">
<map>
<entry key="4">
<bean class="com.home.factoryMethod.Car">
<property name="id" value="4"></property>
<property name="name" value="Honda"></property>
<property name="price" value="300000"></property>
</bean>
</entry> <entry key="6">
<bean class="com.home.factoryMethod.Car">
<property name="id" value="6"></property>
<property name="name" value="ford"></property>
<property name="price" value="500000"></property>
</bean>
</entry>
</map>
</property>
</bean> <!-- 2.use Factory bean to get bean objectr
factory-bean : the bean define above
factory-method: method of get Bean Object
constructor-arg: parameters of factory-method
-->
<bean id="car4" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="4"></constructor-arg>
</bean> <bean id="car6" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="6"></constructor-arg>
</bean>

因为实例工厂本身要实例化, 所以我们可以在xml中 指定它里面容器的data, 解决了上面提到的静态工厂方法的缺点啦

client代码

public static void h2(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factoryMethod.xml");
Car car1 = (Car) ctx.getBean("car4");
System.out.println(car1); car1 = (Car) ctx.getBean("car6");
System.out.println(car1);
}

输出结果

May 31, 2016 12:22:28 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5d79a4c9: startup date [Tue May 31 00:22:28 CST 2016]; root of context hierarchy
May 31, 2016 12:22:28 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [bean-factoryMethod.xml]
Car [id=4, name=Honda, price=300000]
Car [id=6, name=ford, price=500000]

小结

本人觉得实例工厂方式使用起来更加灵活啦, 不过项目中其实本文一开始提到的第三种方法FactoryBean比起工厂方法方式更加常见。

Spring 通过工厂方法(Factory Method)来配置bean的更多相关文章

  1. 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)

    在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...

  2. [设计模式-创建型]工厂方法(Factory Method)

    概括 名称 Factory Method 结构 动机 定义一个用于创建对象的接口,让子类决定实例化哪一个类.Factory Method 使一个类的实例化延迟到其子类. 适用性 当一个类不知道它所必 ...

  3. 设计模式——工厂方法(Factory Method)

    定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. ——DP UML类图 模式说明 抽象业务基类 实际业务类的公共基类,也是工厂要创建的所有对象的父类,这部分 ...

  4. Headfirst设计模式的C++实现——工厂方法(Factory Method)

    引用原书的一句话:所有的工厂模式都用来封装对象的创建,工厂方法模式通过让子类决定该创建的对象是什么来达到封装的目的. Pizza类及其派生类与上一例相同 PizzaStore.h #ifndef _P ...

  5. 设计模式二: 工厂方法(Factory Method)

    简介 工厂方法模式是创建型模式的一种, 核心结构有四个角色: 抽象工厂,具体工厂,抽象产品,具体产品; 实现层面上,该模式定义一个创建产品的接口,将实际创建工作推迟到具体工厂类实现, 一个产品对应一个 ...

  6. 工厂方法 Factory Method

    背景:有一个应用框架,它可以向用户显示多个文档.在这个框架中,两个主要的抽象是类Application和Document.这两个类都是抽象的.客户必须通过它们的子类来做与举替应用相关的实现. 分析:因 ...

  7. 设计模式学习心得<工厂方法 Factory Method>

    概述 意图 业务代码中常常有构造对象的过程,它拥有大量的参数.并且有很多地方需要这对象. 简化对象构造过程. 主要解决 一个类在不同场景的频繁地创建,让不同对象的创建更有语义化,提高代码复用性. 何时 ...

  8. spring 通过工厂方法配置Bean

    概要: 通过调用静态工厂方法创建Bean 调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中.当client须要对象时,仅仅须要简单地调用静态方法,而不用关心创建对象地细节. 要声明通过静 ...

  9. 11.Spring通过工厂方法配置Bean

    通过工厂方法配置Bean暴扣静态工厂方法和实例工厂方法. 1.静态工厂方法 调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单的调用静态方法,而不去关心创建 ...

随机推荐

  1. Jquery获得控件值的方法

    一 Jquery获得服务器控件值的方法 由于ASP.NET网页运行后,服务器控件会随机生成客户端id,jquery获取时候不太好操作,google了下,总结有以下3种方法: 服务器控件代码:<a ...

  2. YII中URL地址美化

    URL地址美化:urlManager地址管理(通过程序来实现url的地址美化) 例如: 原地址:http://localhost/项目/app/index.php?r=控制器/方法 新地址:http: ...

  3. MySQL基本查询语句

    创建一张表 create table user ( id ) not null, name ) not null, birthDate date not null, gender ) not null ...

  4. Servlet & JSP - Decorating Requests and Responses

    Servlet API 提供了四个包装类:ServletRequestWrapper.ServletResponseWrapper.HttpServletRequestWrapper.HttpServ ...

  5. JAVA Web.xml 加载顺序

    web.xml加载过程(步骤): 1.启动WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> ...

  6. hazelcast的坑爹事

    转载自 http://blog.csdn.net/hengyunabc/article/details/18514563 简介 开源中国的简介: Hazelcast是一个高度可扩展的数据分发和集群平台 ...

  7. CDN调度器HAProxy、Nginx、Varnish

    http://www.ttlsa.com/web/the-cdn-scheduler-nginx-haproxy-varnish/ CDN功能如下:1.将全网IP分为若干个IP段组,分组的依据通常是运 ...

  8. Java输出日历

    源码链接:http://pan.baidu.com/s/1o6xeybK

  9. UITableView优化的那些事儿

    作为iOS开发,UITableView可能是平时我们打交道最多的UI控件之一,其重要性不言而喻. 关于TableView,我想最核心的就是UITableViewCell的重用机制了. 简单来说呢就是当 ...

  10. tableview刷新某个区域(section)或者某一行(row)

    //一个section刷新 NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:2]; [tableview reloadSections:in ...