Spring 工厂方法与FactoryBean(实例化Bean) | 您所在的位置:网站首页 › 静态工厂方式实例化管理方案设计 › Spring 工厂方法与FactoryBean(实例化Bean) |
该篇博客关于工厂方法与FactoryBean,其实就是在Spring中不再使用Spring创建Bean实例,而是利用工厂方法与FactoryBean把Bean创建过程转移到开发者手中 该篇博客目录 1、理解工厂方法和FactoryBean是干什么的 2、静态工厂方法实例化Bean 3、工厂方法实例化Bean 4、FactoryBean实例化Bean(工厂Bean) 一、理解工厂方法和FactoryBean是干什么的笔者认为这一块在本篇博客是最重要的,你得理解工厂方法和FactoryBean是干什么的,以及它和哪些是同类 首先通常在Spring中,我们会利用XML或者注解的方式类配置bean。而在XML方式中有三种方式来实例化bean 反射模式工厂方法模式FactoryBean模式其中经常会用到反射模式,即在bean的配置中,声明bean的全类名,而本博客笔者将会介绍工厂模式和FactoryBean模式下实例化bean,对两种模式深入理解其思想 二、静态工厂方法实例化Bean(Static Factory Method)考虑一个场景,在Spring中将一个单例类配置Bean。一般来说,单例类的实例只能通过静态工厂方法创建(笔者这里在《Spring IN ACTION》的例子上进行扩展):以下例子一个舞台类,舞台只有一个,即采用静态工厂方法 Stage.java package com.linjie.staticfactory; /** * @author LinJie * @Description:这是一个舞台单例类(所以需要静态工厂方法) * 每个参赛者用同一个舞台 */ public class Stage { private static Stage instance; public static Stage getInstance() { if(instance == null){ instance = new Stage(); } return instance; } //搭建舞台完成 public void CreateStageSuccess() { System.out.println("舞台搭建完成,舞者可以上台了"); } }Dancer.java(舞者类) package com.linjie.staticfactory; /** * @author LinJie * @Description:这是每个舞者的类,但他们使用同一个舞台 */ public class Dancer { private Stage stage; /** * @param stage the stage to set */ public void setStage(Stage stage) { this.stage = stage; } //LinJie dancer上台 public void Show() { stage.CreateStageSuccess(); System.out.println("LinJie dancer上台"); } }测试类 package com.linjie.staticfactory; /** * @author LinJie * @Description:这是每个舞者的类,但他们使用同一个舞台 */ public class Dancer { private Stage stage; /** * @param stage the stage to set */ public void setStage(Stage stage) { this.stage = stage; } //LinJie dancer上台 public void Show() { stage.CreateStageSuccess(); System.out.println("LinJie dancer上台"); } }applicationContext.xml 结果 舞台搭建完成,舞者可以上台了 LinJie dancer上台注意:Stage没有公开的构造方法,取而代之的是,静态方法getInstance()每次调用都返回相同的实例(因为舞台只有一个),那么在Spring中如何把没有公开构造方法的Stage配置为一个Bean呢? 可以看到在applicationContext.xml中看到 factory-method:允许我们调用一个指定的静态工厂方法,从而代替构造方法来创建一个类的实例(即指定静态工厂方法名)class:不再是Bean实例的实现类,而是Bean实例的静态工厂类(上面的例子没有体现这一点,下面的例子根据这一点来实现)如果静态工厂方法需要参数,使用为其配置Stage.java(一个舞台类,可传名字) package com.linjie.staticfactory; /** * @author LinJie * @Description:一个舞台类,可以给舞台赋值(其实这里我只想演示传参) */ public class Stage { private String name; /** * @param name the name to set */ public void setName(String name) { this.name = name; } //搭建舞台 public void Show() { System.out.println(name+"舞台搭建完成"); } }staticfactory.java(静态工厂方法实现类) package com.linjie.staticfactory; /** * @author LinJie * @Description:这是一个静态工厂方法的类,用于创建单例舞台 */ public class staticfactory { private static Stage instance; public static Stage getInstance() { if(instance == null){ instance = new Stage(); } return instance; } }测试类 package com.linjie.staticfactory; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class staticFactoryBean { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Stage stage = (Stage) context.getBean("stage"); stage.Show(); } }applicationContext.xml 结果 注意:这里的class属性的值不是Bean实例的实现类,而是生成Bean实例的静态工厂类 三、工厂方法实例化Bean(Instance Factory Method)ABean.java(一个Bean实例的实现类) package com.linjie.factory; /** * @author LinJie * @Description */ public class ABean { //利用工厂方法实例化Bean成功显示 public void show() { System.out.println("工厂方法实例化Bean成功"); } }FactoryBean.java(工厂方法) package com.linjie.factory; /** * @author LinJie * @Description:工厂方法实例化Bean */ public class FactoryBean { public ABean getABean() { return new ABean(); } }测试类 package com.linjie.factory; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class FactoryTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ABean abean = (ABean) context.getBean("abean"); abean.show(); } }applicationContext.xml 结果 FactoryBean是Spring容器提供的一种可以扩展容器对象实例化逻辑的接口,请不要将其与容器名称BeanFactory相混淆。FactoryBean,其主语是Bean,定语是Factory,也就是说,它本身与其他注册到容器的对象一样,只是一个Bean而已,只不过这里类型的Bean本身就是生产对象的工厂 应用场景当某些对象的实例话过程过于烦琐,通过XML配置过于复杂,使我们宁愿使用Java代码来完成这个实例化过程的时候,或者,某些第三方库不能直接注册到Spring容器中的时候,就可以实现org.spring-framework.beans.factory.FactoryBean接口,给出自己的对象实例化代码。当然实现自定义工厂也是可以的。但是FactoryBean是Spring的标准 使用方法1、创建FactoryBean的实现类 2、实现以下三个方法 - public String getObject() throws Exception:该方法返回该FactoryBean“生产”的对象。我们需要实现该方法以给出自己对象实例化逻辑 - public Class getObjectType():该方法仅返回getObject()方法所返回的对象的类型。如果预先无法确定,则返回null - public boolean isSingleton() :该方法返回结果用于表明,getObject()“生产”的对象是否要以singleton(单例)形式存于容器中。如果以singleton形式存在,则返回true,否则返回falsenameFactoryBean实现类 package com.linjie.factorybean; import org.springframework.beans.factory.FactoryBean; public class nameFactoryBean implements FactoryBean { //该方法返回该FactoryBean“生产”的对象 //我们需要实现该方法以给出自己对象实例化逻辑 @Override public String getObject() throws Exception { return new String("linjie"); } //该方法仅返回getObject()方法所返回的对象的类型 //如果预先无法确定,则返回null @Override public Class getObjectType() { return null; } //该方法返回结果用于表明,getObject()“生产”的对象是否要以singleton(单例)形式存于容器中 //如果以singleton形式存在,则返回true,否则返回false @Override public boolean isSingleton() { return false; } }测试类 package com.linjie.factorybean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class factorybeanTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); String bean = (String) context.getBean("bean"); System.out.println(bean); } }applicationContext.xml 结果 《Spring揭秘》 《Spring IN ACTION》 |
CopyRight 2018-2019 实验室设备网 版权所有 |