热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

深入了解Spring中的FactoryBean

这篇文章主要介绍了深入了解Spring中的FactoryBean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

FactoryBeanBeanFactory由于在命名上极其相似,一直以来困扰了不少的开发者。

BeanFactory,耳熟能详的Spring核心接口,提供IoC容器的最基本功能。但要解释FactoryBean一句话可能就说不清楚了。我们将从下面的例子逐步说明,FactoryBean是什么,它提供了什么样的能力。

/**
 * 布料
 * 包含颜色属性
 * Created by OKevin On 2019/9/3
 **/
public class Cloth {
 private Red red;
 //省略setter/getter方法
}

当初始化一个Cloth对象时,我希望Red对象也被赋值,此时我将在Cloth的构造方法中new一个Red对象。

public Cloth() {
 red = new Red();
}

但是随着业务的发展,我希望Cloth的颜色属性将是Blue蓝色,这时我将修改代码将Red和Blue类抽象出一个Color接口,Cloth代码将重构:

/**
 * 布料
 * 包含颜色属性
 * Created by OKevin On 2019/9/3
 **/
public class Cloth {
 private Color color;
 public Cloth() {
  color = new Blue();
 }
 //省略setter/getter方法
}

业务又进一步发展,Cloth类中的颜色属性将会根据一定的条件赋值为Red红色,此时我们将代码继续重构:

/**
 * 布料
 * 包含颜色属性
 * Created by OKevin On 2019/9/3
 **/
public class Cloth {
 private Color color;
 public Cloth() {
  if (condition()) {
   color = new Blue(); 
  } else {
   color = new Red();
  }
 }
 //省略setter/getter方法
}

这样的代码的确能运行,但如果有新的条件继续加入到业务中,此时我们又将改动Cloth类的构造方法,而我们认为Cloth方法是一个比较核心的业务对象,不应该经常对它进行修改,并且在构造方法中对于Color对象创建过于冗余,不符合单一职责的原则,所以我们将Color对象的创建过程通过工厂方法模式来完成。

静态工厂方法

我们再次将Cloth类进行如下重构(为了使示例代码更加简洁,下面的示例将只创建Red对象):

/**
 * 布料
 * 包含颜色属性
 * Created by OKevin On 2019/9/3
 **/
public class Cloth {
 private Color color;
 public Cloth() {
  color = StaticColorFactory.newInstance();
 }
 //省略setter/getter方法
}
/**
 * 静态工厂方法
 * Created by OKevin On 2019/9/3
 **/
public class StaticColorFactory {
 public static Color getInstance() {
  return new Red();
 }
}

如果我们在Spring容器中要通过静态工厂方法,创建具体的对象实例应该怎么做呢?

众所周知,要将一个对象实例交由Spring容器管理,我们通常是通过以下XML配置:


 

但此时,Red对象实例并不是由Spring容器管理,而是由静态工厂方法创建的,此时我们应该讲XML配置修改为以下方式:


 

这是Spring支持静态工厂方法创建对象实例的特定方式。这样我们就能在Spring中通过静态工厂方法创建对象实例。

实例工厂方法

有静态工厂方法,就有非静态工厂方法,区别就是方法不是静态的。

/**
 * 实例工厂方法
 * Created by OKevin On 2019/9/3
 **/
public class ColorFactory {
 public Color getInstance() {
  return new Red();
 }
}

实例工厂方法在Spring中XML配置略有不同:


 


通过配置可以看到,我们需要首先在Spring中实例化工厂,再通过工厂对象实例化Red对象。

在有了对工厂方法在Spring中创建对象实例的认识后,FactoryBean实际上就是为我们简化这个操作。下面我们将通过FactoryBean来创建Red对象。

FactoryBean

/**
 * Created by OKevin On 2019/9/3
 **/
public class ColorFactoryBean implements FactoryBean {
 public Color getObject() throws Exception {
  return new Red();
 }
 public Class<&#63;> getObjectType() {
  return Red.class;
 }
 public boolean isSingleton() {
  return false;
 }
}

通过实现FactoryBean的方式,XML配置如下:


 

这样就不用像工厂方法那样配置相应的属性,直接按照普通的Bean注入即可,由于Spring内部做了特殊处理,此时名称为“red”的Bean并不是ColorFactoryBean,而是它方法中getObject中返回的对象。如果实在想要获取ColorFactoryBean的对象实例,则在Bean的名称前加入“&”即可(“&red”)。

看到这里,是否对FactoryBean有了一点认识呢?FactoryBean在Spring中最为典型的一个应用就是用来创建AOP的代理对象。

我们知道AOP实际上是Spring在运行时创建了一个代理对象,也就是说这个对象,是我们在运行时创建的,而不是一开始就定义好的,这很符合工厂方法模式。更形象地说,AOP代理对象通过Java的反射机制,在运行时创建了一个代理对象,在代理对象的目标方法中根据业务要求织入了相应的方法。这个对象在Spring中就是——ProxyFactoryBean。

ProxyFactoryBean

我们将通过比较“古老”的方式创建一个Red对象的切面,在它的print方法执行前和执行后分别执行一条语句。之所以古老是因为我们往往通过注解的方式,而不会这么折磨自己去写一个切面对象。

/**
 * 环绕通知
 * Created by OKevin On 2019/9/4
 **/
public class LogAround implements MethodInterceptor {
 public Object invoke(MethodInvocation invocation) throws Throwable {
  System.out.println("调用目标方法【前】打印日志");
  Object result = invocation.proceed();
  System.out.println("调用目标方法【后】打印日志");
  return result;
 }
}

此时我们需要ProxyFactoryBean的介入为我们创建一个代理对象并由Spring容器管理,根据上面ColorFactoryBean的经验,ProxyFacoryBean也应该如下配置:

答案是肯定的,只是ProxyFactoryBean多了几个参数,既然是生成代理对象,那么目标对象、目标方法就必不可少,实际的XLM配置如下:




 
 
 
 

通过测试程序,ProxyFactoryBean的确生成了一个代理对象。

public class ProxyFactoryBeanTest {
 private ClassPathXmlApplicationContext ctx;
 @Before
 public void init() {
  ctx = new ClassPathXmlApplicationContext("spring-proxyfactorybean.xml");
 }
 @Test
 public void testProxyFactory() {
  Red proxyRed = (Red) ctx.getBean("proxyRed");
  proxyRed.print();
 }
}

所以,FactoryBean为我们实例化Bean提供了一个更为灵活的方式,我们可以通过FactoryBean创建出更为复杂的Bean实例。

本文完整代码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/factorybean

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 【MicroServices】【Arduino】装修甲醛检测,ArduinoDart甲醛、PM2.5、温湿度、光照传感器等,数据记录于SD卡,Python数据显示,UI5前台,微服务后台……
    这篇文章介绍了一个基于Arduino的装修甲醛检测项目,使用了ArduinoDart甲醛、PM2.5、温湿度、光照传感器等硬件,并将数据记录于SD卡,使用Python进行数据显示,使用UI5进行前台设计,使用微服务进行后台开发。该项目还在不断更新中,有兴趣的可以关注作者的博客和GitHub。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
author-avatar
腾云溪牛_556
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有