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配置

  <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);
}

小结

由上面的例子, 静态工厂方法方式是非常适用于作为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写法

 <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> <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);
}

小结

实例工厂方式使用起来更加灵活, FactoryBean比起工厂方法方式更加常见。

Spring工厂方法(factory-bean)配置bean的更多相关文章

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

    Spring 通过工厂方法(Factory Method)来配置bean 在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. ...

  2. 跟着刚哥学习Spring框架--通过XML方式配置Bean(三)

    Spring配置Bean有两种形式(XML和注解) 今天我们学习通过XML方式配置Bean 1. Bean的配置方式 通过全类名(反射)的方式   √ id:标识容器中的bean.id唯一. √ cl ...

  3. 跟着刚哥学习Spring框架--通过注解方式配置Bean(四)

    组件扫描:Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件. 特定组件包括: 1.@Component:基本注解,识别一个受Spring管理的组件 2.@Resposit ...

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

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

  5. Spring 工厂方法创建Bean 学习(三)

    1, 静态工厂方法创建Bean 调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节. 要声明通过静态方法创建 ...

  6. 4. Spring 如何通过 XML 文件配置Bean,以及如何获取Bean

    在 Spring 容器内拼凑 bean 叫做装配.装配 bean 的时候,你是在告诉容器,需要哪些 bean ,以及容器如何使用依赖注入将它们配合在一起. 理论上,bean 装配的信息可以从任何资源获 ...

  7. spring笔记--通过注解(annotation)配置Bean

    Spring能够在classpath下自动扫描,侦测和实例化具有特定注解的组件,这在Spring中成为组件扫描(Component scanning). 特定组件的注解包括: @Component:基 ...

  8. Spring 在xml文件中配置Bean

    Spring容器是一个大工厂,负责创建.管理所有的Bean. Spring容器支持2种格式的配置文件:xml文件.properties文件,最常用的是xml文件. Bean在xml文件中的配置 < ...

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

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

随机推荐

  1. Java内存模型与指令重排

    Java内存模型与指令重排 本文暂不讲JMM(Java Memory Model)中的主存, 工作内存以及数据如何在其中流转等等, 这些本身还牵扯到硬件内存架构, 直接上手容易绕晕, 先从以下几个点探 ...

  2. 关于Django升级的一些联想

    刚刚阅读完django1.11的release note,从django1.4一直用到django1.11,以及即将到来的大版本django2.0,Django的版本升级策略和国内的技术现状对比称得上 ...

  3. Nginx接收的host值会影响alias的规则匹配

    一般内网接收的HTTP请求都是内网唯一的网关传过来的,nginx的alias匹配会直接使用网关穿过的host值,而不是从URL解析出来的,从而导致的问题是,容器的alias相关Server_name规 ...

  4. 与班尼特·胡迪一起拿奖学金(HZNU-2273)

    与班尼特·胡迪一起拿奖学金 AC Time Limit:  2 s      Memory Limit:   256 MB Description 班尼特·胡迪这学期的体测终于上80分了,当期末考试的 ...

  5. 图片与base64的互转

    /// <summary>        /// 把图片转换到文本信息        /// </summary>        /// <param name=&quo ...

  6. Python_struct模块操作二进制文件

    ''' 使用struct模块写入二进制文件 ''' import struct n=130000000 x=96.45 b=True s='a1@中国' sn=struct.pack('if?',n, ...

  7. 进阶-Redis 知识梳理

    redis介绍 1.什么是NoSQL NoSQL(统称),泛指非关系型的数据库,NoSQL即Not-Only SQL,它可以作为关系型数据库的良好补充. 2.NoSQL数据库的四大分类如下: 键值(K ...

  8. 使用input file上传文件中onChange事件只触发一次问题

    每次上传文件的时候,都会将当前的文件路径保存至$event.target.value中,当第二次选择文件时,由于两次$event.target.value相同,所以不会触发change事件. 解决方案 ...

  9. JSP中的隐含对象

    什么是JSP中隐含对象:容器自动创建,在JSP文件中可以直接使用的对象. 作用:JSP预先创建的这些对象可以简化对HTTP的请求,响应信息的访问. JSP中的隐含对象: 输入输出对象:request. ...

  10. 使用jmeter 进行接口的性能测试

    1.启动jmeter:在bin下以管理员身份运行jmeter.bat,启动jmeter 2. 创建测试计划: 默认启动jmeter时会加载一个测试技术模板,保存测试计划:修改名称为Apitest,点击 ...