假设第三方(or别的team)提供一个工厂类(此类是不能够改动的。往往以jar包形式提供的),须要供给我们项目来使用。

可是我们自己的项目使用了spring来配置,所以我们当然希望可以通过spring的aop来配置这个工厂类来,来创建实例以进行引用。

可是这个工厂类的源码比較特殊。例如以下:

package x.y;

import java.util.Properties;

import x.y.client.CmdClient;
import x.y.client.InternalCmdClient; public class ClientFactory {
private static volatile CmdClient cmdclient;
private static volatile InternalCmdClient cmdinternalclient;
private static Properties props = new Properties(); public static void setEnv(String env){
props.put( "env", env );
} public static CmdClient getCmdClient() throws Exception{
if ( cmdclient == null ) {
synchronized ( CmdClientImpl.class ) {
if ( cmdclient == null ) {
cmdclient = new CmdClientImpl( props );
}
}
}
return cmdclient;
} public static InternalCmdClient getIntenalCmdClient() throws Exception{
if ( cmdinternalclient == null ) {
synchronized ( InternalCmdClientImpl.class ) {
if ( cmdinternalclient == null ) {
cmdinternalclient = new InternalCmdClientImpl( props );
}
}
}
return cmdinternalclient;
} public static void destoryClient(){
if ( cmdclient != null ) {
cmdclient.destroy();
cmdclient = null;
} if ( cmdinternalclient != null ) {
cmdinternalclient.destroy();
cmdinternalclient = null;
}
} }

介绍如上工厂类的特殊性:

  1. 全部的方法属性都是静态的。
  2. setEnv() 是静态方法:内部是往静态属性props设值。
  3. 两个工厂方法。是静态空參方法(这是符合工厂方法定义的)。内部的实现是依据已经设置好的props来实例化对象,假设參数(env)没有设值,那么实例化对象就会失败。所以我们就须要先setEnv,在通过工厂方法实例化对象。

一:有人会说,这个非常easy。依据spring的官方文档。用“静态工厂方法”进行实例化。

可是此方法不可取,例如以下所述:


	<bean id="internalClient" class="x.y.ClientFactory"
factory-method="getIntenalCmdClient" destroy-method="destroy">
<property name="env" value="${env}" />
</bean>

如上配置。实例化internalClient会失败!原因:

  1. spring尽管会调用setEnv()方法。可是并非调用x.y.ClientFactory类里面的此方法,而是调用internalClient实例里面的setEnv()方法。

    所以此<property>的配置是无效的。

  2. 另外工厂方法getIntenalCmdClient会被首先调用(能够debug断点),然后spring再调用setEnv方法。因此在调用getIntenalCmdClient时候没有不论什么env參数被传入。
  3. 以上两条都会导致实例化失败。


二:会有人说既然“静态工厂化方法”不可取,那么spring官方文档里面还提供了“实例工厂方法”。可是此方法也是不可取的,例如以下所述:

	<bean id="clientFactory"
class="x.y.ClientFactory">
<property name="env" value="${env}" />
</bean>
<bean id="internalClient" factory-bean="clientFactory"
factory-method="getIntenalCmdClient" destroy-method="destroy">
</bean>
如上配置。实例化internalClient会失败!原因:
  1. 实例化clientFactory,其目的是为了让spring调用setEnv方法。往x.y.ClientFactory类里面设值(静态属性env设值),由于设置了factory-bean属性。所以clientFactory的实例化顺序会先于internalClient。到眼下没有什么问题。可是问题出如今第二点
  2. 工厂方法gentIntenalCmdClient是静态方法。设置了factory-bean属性的含义就是clientFactory.getIntenalCmdClient如此调用,在spring里面不支持对象引用静态方法!因此是报错的。
  3. spring报错log:“No matching factory method found: factory bean 'clientFactory'; factory method 'getIntenalCmdClient()'. Check that a method with the specified name exists and that it is non-static.”

综上两种情况。我想出了解决方法。

  1. 实例化clientFactory bean还是需要的,由于必需要保证env能够最先set值(静态方法setEnv()能够最先被调用)。
  2. 实例化internalClient bean使用"静态工厂方法"。如此就能够成功的调用静态工厂方法(ClientFactory.getIntenalCmdClient())
  3. 为保证先setEnv,再调用工厂方法(ClientFactory.getIntenalCmdClient()),能够使用depends-on属性
  4. destroy-method所设值的方法。是internalClient实例所能引用到的方法。

配置例如以下:

<bean id="internalClient" class="x.y.AhClientFactory"
factory-method="getIntenalCmdClient" destroy-method="destroy"
depends-on="clientFactory">
</bean>
<bean id="clientFactory" class="x.y.ClientFactory">
<property name="env" value="${env}" />
</bean>

如有不正确的or更好的解决方式,望大哥赐教!

BTW:

   实例工厂和静态工厂一样的同样限制:

  1. 静态工厂方法上不能有參数,也不能在Spring种定义静态工厂方法的參数。

  2. 静态工厂方法仅仅能是public的,不能是private或protected的。

  3. 静态工厂方法不能和构造函数注入一起使用。
    实例工厂和静态工厂不同的点:
  • 实例工厂方法不能是静态的,而静态工厂方法必须是静态的。

Spring通过工厂创建实例的注意事项的更多相关文章

  1. 4.spring对象的创建(静态工厂 实例工厂 泛型,嵌套类型)

    1.原料类 namespace CreateObjects{    public class GenericClass<T>    { }} PersonDao 类 包含嵌套类型 name ...

  2. Spring基础(3) : 静态工厂和实例工厂创建bean

    public class Factory { public static Person staticCreate(){ Person p = new Person(); p.name="st ...

  3. [原创]java WEB学习笔记102:Spring学习---Spring Bean配置:bean配置方式(工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean) 全类名

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  4. 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-使用工厂创建代理(Using the ProxyFactoryObject to create AOP proxies)

    本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 如果你正在为你的业务模型使用 ...

  5. Spring 静态工厂实例

    直接上代码,看注释. 创建实体类: package com.spring.classs; public class Test {    private String name;    private ...

  6. Spring实例化Bean三种方法:构造器、静态工厂、实例工厂

    Spring中Bean相当于java中的类,可以通过xml文件对bean进行配置和管理. 一.Bean的实例化: 构造器实例化.静态工厂实例化.实例工厂方式实例化. 目录: 构造器实例化: xml配置 ...

  7. java:Spring框架2(bean的作用域,静态工厂和实例工厂,自动装配,动态代理)

    1.bean的作用域,静态工厂和实例工厂: bean.xml: <?xml version="1.0" encoding="UTF-8"?> < ...

  8. 【Spring】Spring中的Bean - 2、Baen的实例化 (构造器、静态工厂、实例工厂)

    Bean的实例化 文章目录 Bean的实例化 构造器实例化 静态工厂方式实例化 实例工厂方式实例化 简单记录-Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)-S ...

  9. Spring第一课:基于XML装配bean(四),三种实例化方式:默认构造、静态工厂、实例工厂

    Spring中基于XML中的装配bean有三种方式: 1.默认构造 2.静态工厂 3.实例工厂 1.默认构造 在我们在Spring的xml文件中直接通过:     <bean id=" ...

随机推荐

  1. 王立平--android事件监听的3种方式

    第一种通常在activity组件的oncreate事件中直接定义,直接动作. 这样的方式每一个控件都定义一次.通常不方便. Button btn = (Button) findViewById(R.i ...

  2. Phalcon框架中的另类使用

    不像传统的PHP框架,假设框架想被还有一个框架使用仅仅能通过rpc或是引入文件等的方式.Phalcon能够在其他框架中直接使用.这是因为Phalcon是以扩展的形式存在的,在server载入时会直接载 ...

  3. 写了交互给后台后来不能用?bug多多多又找不到文件效率低?工作流程帮你优化起来~~~~

    前端工作流程(多方交互篇) 新的网页: 1.跟美工沟通,跟产品沟通,跟后台沟通.前两者主要是页面样式.后者主要是表单交互.用哪个框架之类的. 2.实现.(写清楚哪块是用什么验证方式的)→ 给后台. 3 ...

  4. PyconChina2015丁来强Pydata Ecosystem

    pydata ecosystem基于python的数据分析生态系统 0. Agenda Data Science ecosystem Data Wrangling Data Analysis Data ...

  5. VirtualBox虚拟机安装RedHat7.3编译Linux0.01内核

    引子 由于需要编译linux0.01内核,而目前的linux版本太高需要降低gcc版本等等,需要做不少调整非常不方便. 所以,直接安装RedHat7.3,这样就好编译linux0.01的内核了. 但是 ...

  6. CCIE路由实验(2) -- BGP选路原则

    BGP路径属性分为4类: 公认必遵(Well-Known Mandatory):BGP更新报文中必须包含的,且必须被所有BGP厂商实现所能识别的,包括ORIGIN,AS-PATH和Next_Hop 1 ...

  7. 常用位操作,读8位 I2C 1302 18B20 .

    /*1302*/ unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) { unsigned char i; for(i=8; i>0; ...

  8. [置顶] T-sql sql server 设置主键约束、标示列、唯一约束、默认值、约束、创建表

    ----选择数据库 use ythome go ----查看表是否存在 if Exists ( select * from sysobjects where name='sys_menu' and t ...

  9. HDU 1150:Machine Schedule(二分匹配,匈牙利算法)

    Machine Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  10. Android基础【1】杀死进程(强行停止)应用程序的方法

    写在前面: 进入手机ODM已经很久,经历过几个项目项目下来,对高通.展讯.Marvell平台都进行了接触,对于我个人来说,参与手机系统项目的开发与维护,最明显的好处是可以深入的了解某一功能的具体实现过 ...