首页 技术 正文
技术 2022年11月15日
0 收藏 865 点赞 3,451 浏览 3153 个字

假设第三方(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 CmdClientcmdclient;
private static volatile InternalCmdClientcmdinternalclient;
private static Propertiesprops= 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. 静态工厂方法不能和构造函数注入一起使用。

    实例工厂和静态工厂不同的点:

  • 实例工厂方法不能是静态的,而静态工厂方法必须是静态的。
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,489
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,904
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,737
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,490
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,128
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,290