Spring通过工厂创建实例的注意事项
假设第三方(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;
- }
- }
- }
介绍如上工厂类的特殊性:
- 全部的方法属性都是静态的。
- setEnv() 是静态方法:内部是往静态属性props设值。
- 两个工厂方法。是静态空參方法(这是符合工厂方法定义的)。内部的实现是依据已经设置好的props来实例化对象,假设參数(env)没有设值,那么实例化对象就会失败。所以我们就须要先setEnv,在通过工厂方法实例化对象。
可是此方法不可取,例如以下所述:
- <bean id="internalClient" class="x.y.ClientFactory"
- factory-method="getIntenalCmdClient" destroy-method="destroy">
- <property name="env" value="${env}" />
- </bean>
如上配置。实例化internalClient会失败!原因:
- spring尽管会调用setEnv()方法。可是并非调用x.y.ClientFactory类里面的此方法,而是调用internalClient实例里面的setEnv()方法。
所以此<property>的配置是无效的。
- 另外工厂方法getIntenalCmdClient会被首先调用(能够debug断点),然后spring再调用setEnv方法。因此在调用getIntenalCmdClient时候没有不论什么env參数被传入。
- 以上两条都会导致实例化失败。
二:会有人说既然“静态工厂化方法”不可取,那么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>
- 实例化clientFactory,其目的是为了让spring调用setEnv方法。往x.y.ClientFactory类里面设值(静态属性env设值),由于设置了factory-bean属性。所以clientFactory的实例化顺序会先于internalClient。到眼下没有什么问题。可是问题出如今第二点
- 工厂方法gentIntenalCmdClient是静态方法。设置了factory-bean属性的含义就是clientFactory.getIntenalCmdClient如此调用,在spring里面不支持对象引用静态方法!因此是报错的。
- 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.”
- 实例化clientFactory bean还是需要的,由于必需要保证env能够最先set值(静态方法setEnv()能够最先被调用)。
- 实例化internalClient bean使用"静态工厂方法"。如此就能够成功的调用静态工厂方法(ClientFactory.getIntenalCmdClient())
- 为保证先setEnv,再调用工厂方法(ClientFactory.getIntenalCmdClient()),能够使用depends-on属性
- 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:
- 静态工厂方法上不能有參数,也不能在Spring种定义静态工厂方法的參数。
- 静态工厂方法仅仅能是public的,不能是private或protected的。
- 静态工厂方法不能和构造函数注入一起使用。
- 实例工厂方法不能是静态的,而静态工厂方法必须是静态的。
Spring通过工厂创建实例的注意事项的更多相关文章
- 4.spring对象的创建(静态工厂 实例工厂 泛型,嵌套类型)
1.原料类 namespace CreateObjects{ public class GenericClass<T> { }} PersonDao 类 包含嵌套类型 name ...
- Spring基础(3) : 静态工厂和实例工厂创建bean
public class Factory { public static Person staticCreate(){ Person p = new Person(); p.name="st ...
- [原创]java WEB学习笔记102:Spring学习---Spring Bean配置:bean配置方式(工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean) 全类名
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-使用工厂创建代理(Using the ProxyFactoryObject to create AOP proxies)
本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 如果你正在为你的业务模型使用 ...
- Spring 静态工厂实例
直接上代码,看注释. 创建实体类: package com.spring.classs; public class Test { private String name; private ...
- Spring实例化Bean三种方法:构造器、静态工厂、实例工厂
Spring中Bean相当于java中的类,可以通过xml文件对bean进行配置和管理. 一.Bean的实例化: 构造器实例化.静态工厂实例化.实例工厂方式实例化. 目录: 构造器实例化: xml配置 ...
- java:Spring框架2(bean的作用域,静态工厂和实例工厂,自动装配,动态代理)
1.bean的作用域,静态工厂和实例工厂: bean.xml: <?xml version="1.0" encoding="UTF-8"?> < ...
- 【Spring】Spring中的Bean - 2、Baen的实例化 (构造器、静态工厂、实例工厂)
Bean的实例化 文章目录 Bean的实例化 构造器实例化 静态工厂方式实例化 实例工厂方式实例化 简单记录-Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)-S ...
- Spring第一课:基于XML装配bean(四),三种实例化方式:默认构造、静态工厂、实例工厂
Spring中基于XML中的装配bean有三种方式: 1.默认构造 2.静态工厂 3.实例工厂 1.默认构造 在我们在Spring的xml文件中直接通过: <bean id=" ...
随机推荐
- android 修改背景色(转)
修改为黑底白字 修改AndroidManifest.xml把android:theme="@style/AppTheme" 修改为android:theme="@andr ...
- CSS中border-style的属性
属性可能的值 值 描述 none 定义无边框. hidden 与 "none" 相同.不过应用于表时除外,对于表,hidden 用于解决边框冲突. dotted 定义点状边框.在大 ...
- 正确的lnamp支持SSI的方法!即支持SHTML和include调用!
正确的lnamp支持SSI的方法!即支持SHTML和include调用! 个地方:一个是apache和nginx里的conf文件 第一步:修改apache里的httpd.conf文件 查找:AddTy ...
- Android开发之TextView排版问题
下面直接是关于解决该问题的代码(根据别人的代码进行了修正以及测试,保证可以修改字体尺寸.颜色.根据padding调整,如果需要支持其他的格式可以将对应的属性添加至Paint类型的对象中): 1 p ...
- 【Web】CGI与Servlet技术对比
CGI:Common Gateway Interface,通用网关接口. 1.CGI处理步骤 首先,客户端(即Web浏览器)根据某资源的URL向Web服务器提出请求:Web服务器的守护进程(HTTP ...
- Windows(64位IIS)未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序
在Windows 7(32位)用.Net开发的Excel导入数据表功能,测试后一切正常,站点发布挪到Windows Server 2008(64位)上就意外了,出现错误提示,运行程序,抛出异常:未在本 ...
- if简单的写法之范围
/* Name:if的范围 Copyright: By.不懂网络 Author: Yangbin Date:2014年2月9日 03:22:32 Description: */ # include & ...
- 浙江工商大学15年校赛C题 我删我删,删删删 【简单模拟】
Description: 有一个大整数.不超过1000位.假设有N位.我想删掉其中的任意S个数字.使得删除S位后,剩下位组成的数是最小的. Input: 有多组数据数据,每组数据为两行.第一行是一个大 ...
- POJ2395 最小生成树 - Prime算法
题目: Out of Hay Time Limit: 1000MS Memory Limit: 65536K Total Submissions: Accepted: Description The ...
- 函数可以作为Javascript对象(哈希表)的键吗
一般Javascript书在讲解对象时,都指出Javascript中的对象可以作为哈希表,存储键值数据.通常情况下,键为字符串,如果键是数字的话,实际上在内部也会转换为字符串. 比如 var o = ...