JiveJdon Community Forums
在线89人 J道首页 | 论坛首页 | 培训咨询 | 开源框架 | 精华 | 查搜 | 注册 | 登陆 |
首页 » 论坛 » 设计模式、框架和架构
???en_US.forumThreadPrev.name??? 上一主题
Go back to the topic listing   返回主题列表
???en_US.forumThreadNext.name??? 下一主题
这个主题共有 18 回复 / 2 页 [ 1 2 下一页 ]  发表新帖子  回复该主题贴
stephen

发表文章: 19
注册时间: 2003年06月24日 15:55
使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月07日 15:39 回复
希望能实现一个对象池,但是同时要避免调用returnObject。
因为如果可以避免调用returnObject,那么就原来的代码就可以不做修改就能使用对象池优化功能了。

下面是为了实现上述功能写的示例代码。

先声明一点,准备保存到池里面的对象是不用在两次调用之间保存状态的。
所以下面的示例代码中,每次调用一个方法的时候,都从池里面找一个对象,用完之后,立即归还。
所以原来的代码中,每次使用对象的时候,从工厂里面new一个对象出来,使用完了也不做任何处理。
类似如下代码。


....
SamplePortType obj = new SampleClass();
obj.helloWorld();
....



另外,由于是示例代码,所以里面涉及多线程同步的问题也做处理。

代码虽然写了出来,就这个示例程序来说,也能跑了,
但是对其中的实现方法存在一些疑问。

主要的疑问是,示例代码中,Proxy.newProxyInstance 每次都是使用同样的一个对象来创建动态代理,
然后实际invoke(Object proxy, Method method, Object[] args)的时候,使用另外一个对象去执行。
不知道这样做会不会存在问题?

不知道为了实现刚开始提出的问题,有什么其他办法?


import java.util.logging.*;
import java.util.Stack;
import java.lang.reflect.*;
import java.lang.Object;
import java.lang.System;

interface SamplePortType {
public void helloWorld ( );
};

class SampleClass implements SamplePortType {
public SampleClass ( ) { }
public void helloWorld ( ) {
System.out.println ( "Hello world!" );
}
};

class SamplePool {
static private SamplePool _instance;
static public SamplePool getInstance() {
if ( null == _instance ) {
_instance = new SamplePool();
}
return _instance;
}

private SamplePool ( ) { _pool = new Stack(); }

public SamplePortType borrowObject ( ) {
if ( _pool.empty() ) {
return new SampleClass();
} else {
return (SamplePortType)_pool.pop();
}
}

public void returnObject ( SamplePortType obj ) { _pool.push ( obj ); }

private Stack _pool;
};

public class AOPHandler implements InvocationHandler {
static private SamplePortType _orgObject = null;

public static SamplePortType getObject ( ) {
if ( null == _orgObject ) _orgObject = new SampleClass();
return (SamplePortType)Proxy.newProxyInstance(
_orgObject.getClass().getClassLoader(),
_orgObject.getClass().getInterfaces(),
new AOPHandler() );
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

SamplePortType obj = SamplePool.getInstance().borrowObject();
Object result = null;
result = method.invoke(obj, args);
SamplePool.getInstance().returnObject ( obj );
return result;
}

static public void main ( String args[] ) {
SamplePortType obj = AOPHandler.getObject();
obj.helloWorld ( );
}
}

stephen

发表文章: 19
注册时间: 2003年06月24日 15:55
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月07日 15:49 回复
上面的描述有些错别字,论坛好像没有办法对已经发表的帖子做修改,所以在这里加以说明一下:

1.所以原来的代码中,每次使用对象的时候,从工厂里面new一个对象出来,使用完了也不做任何处理。
类似如下代码。


....
SamplePortType obj = SampleFactory.getObject();
obj.helloWorld();
....


2.另外,由于是示例代码,所以里面涉及多线程同步的问题也“没”做处理。
stephen

发表文章: 19
注册时间: 2003年06月24日 15:55
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月07日 18:49 回复
http://www.smth.edu.cn/bbsanc.php?path=%2Fgroups%2Fdevelop.faq%2FJavaExpress%2Fjavaprogramming%2FJ2EE%2FAOP%2Fgty5

转贴一篇类似的讨论


☆─────────────────────────────────────☆
gty (宜良-丽江-蝴蝶泉) 于 (Fri Feb 21 02:33:56 2003) 提到:

Session Pool Design

1. 利用apache common-pool实现一个Session Pool(非常简单)
2. 如何避免代码中的returnObject()?

xxx() invoke
--------> PoolProxy ---> PoolInterceptor SessionPool
borrowObject()
--------------->
<---------------


xxx() Session (be borrowed)
-------------------------------->

returnObject()
---------------->



☆─────────────────────────────────────☆
gty (宜良-丽江-蝴蝶泉) 于 (Fri Feb 21 02:38:01 2003) 提到:

RMI design

xxx() invoke Serialize call to remote
-----> ClientProxy ---> RmiInterceptor ------------------->

find ServerProxy, xxx() xxx()
RmiServer----------------> ServerProxy --->....-->ServerObject



☆─────────────────────────────────────☆
gty (宜良-丽江-蝴蝶泉) 于 (Fri Feb 21 02:43:37 2003) 提到:

Method cache design

1.用HashMap做cache

xxx() invoke
-----> Proxy ---> MCInterceptor
1. get Attribute @timeout
2. 用object[]作为key,看cache中的
结果是否超时

3. 如果超时 invoke
------------------> NextInterceptor...
4. 如果不超,返回被cache的结果



☆─────────────────────────────────────☆
gty (宜良-丽江-蝴蝶泉) 于 (Fri Feb 21 02:47:03 2003) 提到:

Draw activity UML diagram:

1. 实现绘图模块
xxx() invoke
---> Proxy ---> ActivityIntercpetor
draw xxx()
--------------->绘图模块
invoke
--------------------------->NextInterceptor...



☆─────────────────────────────────────☆
gty (宜良-丽江-蝴蝶泉) 于 (Fri Feb 21 02:53:04 2003) 提到:

Persistence and descriptive transaction

1. Persistence直接使用Hibernate


xxx invoke
---->Proxy-->HibernateInterceptor
1. 取得@tx,应该为required,requiresnew
,supports,notsupported中的一种
2. 判断当前的transaction状态
3. 决定本次调用是否在transaction当中



☆─────────────────────────────────────☆
gty (宜良-丽江-蝴蝶泉) 于 (Fri Feb 21 03:01:18 2003) 提到:

Folder-Node关系的复用


getFolder() getFolder() invoke getFolder()
--->UserProxy ------> NodeProxy -->SideEntityInterceptor--> Node
return Folder
<-----
根据Folder创建Group proxy
返回GroupProxy
<----


in the code, like this:

...
User user = userFactory.find("guty"); //user is actually a proxy
Group group = (Group)((Node)user).getFolder();
ljshan

发表文章: 15
注册时间: 2004年11月29日 14:18
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月07日 18:57 回复
为什么创建动态代理的时候,对象不从pool中去取呢?另外对象池为什么要用堆栈处理,我觉得用HashSet这样的随机顺序比较好。
public static SamplePortType getObject2() {
SamplePortType _orgObject = SamplePool.getInstance().borrowObject();
return (SamplePortType) Proxy.newProxyInstance(
_orgObject.getClass().getClassLoader(),
_orgObject.getClass().getInterfaces(),
new AOPHandler());
}

这样处理的话,都是随机的了。
ljshan

发表文章: 15
注册时间: 2004年11月29日 14:18
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月07日 19:06 回复
或者更加简洁安全的做法:
public static SamplePortType getObject2() {
SamplePortType _orgObject = new SamplePortType(){
public void helloWorld (){}
};
return (SamplePortType) Proxy.newProxyInstance(
_orgObject.getClass().getClassLoader(),
_orgObject.getClass().getInterfaces(),
new AOPHandler());
}
stephen

发表文章: 19
注册时间: 2003年06月24日 15:55
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月07日 19:31 回复
1.这里的代码都是示例代码,所以pool里面使用stack只是临时的选择。
为了能写一个很小的程序,并且随手copy paste之后,
用javac命令行就能跑起来看结果。
真正用的时候,考虑使用apache的common-pool。

2.上面的代码写的不够清晰,改为如下所示。
注意, _orgObject 是static的。
而这个也正是存在疑问的地方。
应为 _orgObject 是 static 的,所以通过 AOPHandler.getObject
返回的每个 动态代理 对象包含的都是同一个 _orgObject。
不知道这样做有没有问题?


public class AOPHandler implements InvocationHandler {
static private SamplePortType _orgObject = new SampleClass();

public static SamplePortType getObject ( ) {
return (SamplePortType)Proxy.newProxyInstance(
_orgObject.getClass().getClassLoader(),
_orgObject.getClass().getInterfaces(),
new AOPHandler() );
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

SamplePortType obj = SamplePool.getInstance().borrowObject();
Object result = null;
result = method.invoke(obj, args);
SamplePool.getInstance().returnObject ( obj );
return result;
}

static public void main ( String args[] ) {
SamplePortType obj = AOPHandler.getObject();
obj.helloWorld ( );
}
}
stephen

发表文章: 19
注册时间: 2003年06月24日 15:55
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月08日 17:56 回复
之前没详细看 jdk 的文档,只看了一个别人写的例子,以为
Proxy.newProxyInstance的时候一定要有一个对象实例,
后来看了 jdk 的文档,其实不需要有一个实例就可以
Proxy.newProxyInstance了。


public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler h)
throws IllegalArgumentException

Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);



多谢banq的提示,现在重写了一下代码,如下所示。


import java.util.logging.*;
import java.util.Stack;
import java.lang.reflect.*;
import java.lang.Object;
import java.lang.System;

interface SamplePortType {
public void helloWorld ( );
};

class SampleClass implements SamplePortType {
public SampleClass ( ) { }
public void helloWorld ( ) {
System.out.println ( "Hello world!" );
}
};

class SamplePool {
static private SamplePool _instance;
static public SamplePool getInstance() {
if ( null == _instance ) {
_instance = new SamplePool();
}
return _instance;
}

private SamplePool ( ) { _pool = new Stack(); }

public SamplePortType borrowObject ( ) {
if ( _pool.empty() ) {
return new SampleClass();
} else {
return (SamplePortType)_pool.pop();
}
}
public void returnObject ( SamplePortType obj ) { _pool.push ( obj ); }

private Stack _pool;
};

public class AOPHandler implements InvocationHandler {

public static SamplePortType getObject ( ) {
return (SamplePortType)Proxy.newProxyInstance(
SamplePortType.class.getClassLoader(),
SampleClass.class.getInterfaces(),
//SamplePortType.class.getInterfaces(),
new AOPHandler() );
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

SamplePortType obj = SamplePool.getInstance().borrowObject();
Object result = null;
try {
result = method.invoke(obj, args);
} finally {
SamplePool.getInstance().returnObject ( obj );
}

return result;
}

static public void main ( String args[] ) {
SamplePortType obj = AOPHandler.getObject();
obj.helloWorld ( );
}
}



banq

发表文章: 8929
注册时间: 2002年08月03日 17:08
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月13日 14:31 回复



你的代码我觉得可以,invoke方法要做一些Catch就更成熟,
这样执行出错时也可以returnObject。

你这个例子其实是使用动态代理实现AOP的一个实例。

使用AOP的思路,可以彻底将对象池和应用程序分离开,
客户端调用PetshopServiceTarget,只要调用getBean(“businessObject”)即可,
实际就是从对象池中获取的。
Spring的例程Petshop,在其中主要配置:



<bean id=“poolTargetSource“
class=“spring.CommonsPoolTargetSource">
<property name=
"targetBeanName">
<value>petshopServiceTarget</value>
</property>
<property name=
"maxSize">
<value>25</value>
</property>
</bean>
<bean id=
"businessObject"
class=org.springframework.aop.framework.ProxyFactoryBean
">
<property name=
"targetSource">
<ref local=
"poolTargetSource"/>
</property>
<property name=
"interceptorNames">
<value>myInterceptor</value>
</property>
</bean>

凤舞凰扬

发表文章: 26
注册时间: 2004年03月10日 14:25
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月13日 17:23 回复
不清楚楼主的目的是什么,下面我贴出部分我以前写的程序,和你的很类似,通过动态代理产生业务代理层,同时封装事务调用,并且采用配置文件的方式决定对象的产生方式(singleton,unlimited , poolable),
public class BeanFactory {
....
private Object getBeanProxy(BeanConfiguration config)
throws UtilException {
Object bean = null ;
Object proxy = null ;
TransactionDelegate delegate = null ;
String beanName = config.getImpl();
String[] interfaceNames = config.getName();
Class[] cls = new Class[interfaceNames.length] ;
try {
for (int i = 0; i < interfaceNames.length; i++) {
System.out.println("cls ="+interfaceNames);
cls = Class.forName(interfaceNames.trim()) ;
}
if (BeanConfiguration.SINGLETON.equals(config.getMethod())) {
bean = cache.getFromCache(beanName) ;
if (bean == null) {
bean = Class.forName(beanName).newInstance() ;
cache.putIntoCache(beanName , bean) ;
}
delegate = new TransactionDelegate() ;
delegate.setObject(bean) ;
proxy = Proxy.newProxyInstance(delegate.getClass().getClassLoader() ,
cls , delegate) ;
} else if (BeanConfiguration.UNLIMITED.equals(config.getMethod())) {
bean = Class.forName(beanName).newInstance() ;
delegate = new TransactionDelegate();
delegate.setObject(bean);
proxy = Proxy.newProxyInstance(delegate.getClass().getClassLoader() ,
cls , delegate);
} else if (BeanConfiguration.POOLED.equals(config.getMethod())) {
ServiceLog.debug("beanPool instance ="+beanPool);
if (beanPool == null) {
throw new UtilException("系统没有发现相应的池,不支持池管理Bean" , -1);
}
ServiceLog.info("current facade bean pool active num is ="+beanPool.currentActiveNum(beanName));
ServiceLog.info("current facade bean pool idle num is ="+beanPool.currentIdleNum(beanName));
bean = beanPool.get(beanName) ;
delegate = new TransactionDelegate() ;
delegate.setObject(bean);
ServiceLog.info("current facade bean pool size is ="+delegate);
proxy = Proxy.newProxyInstance(delegate.getClass().getClassLoader() ,
cls , delegate);
} else {
throw new UtilException("错误的池的Bean管理方式" , -1);
}
System.out.println("从池中取出的bean 为="+bean);
return proxy ;
} catch (UtilException ex) {
ex.printStackTrace();
ServiceLog.error(ex.getMessage() , ex);
throw ex ;
} catch (Exception ex) {
ex.printStackTrace();
ServiceLog.error(ex.getMessage() , ex);
throw new UtilException(ex);
}
}
......
}



package com.goldenchance.amis.framework.proxy;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import com.goldenchance.common.framework.OperationService;
import com.goldenchance.common.exception.FacadeAccessException;
import com.goldenchance.common.util.TransactionContext;
import com.goldenchance.common.util.TransactionContextFactory;
import com.goldenchance.common.log.ServiceLog;
import java.util.*;
import java.lang.reflect.*;
/**
* 事务代理类
* <p>Title: 实时监控系统</p>
* <p>Description: 通过动态代理技术,实现事务处理的动态封装</p>
* @version 1.0
*/
public class TransactionDelegate implements InvocationHandler {
private final static List DEFAULT_METHOD_LIST = new ArrayList();
private TransactionContextFactory factory ;
private Object object;

public TransactionDelegate() {
factory = TransactionContextFactory.newFactory();
}

public void finalize() {
this.release();
}

public void release() {
object = null ;
}

/**
* 将Object对象中的方法设置为纳入默认忽略的方法集合中
*/
static {
DEFAULT_METHOD_LIST.add("equals");
DEFAULT_METHOD_LIST.add("getClass");
DEFAULT_METHOD_LIST.add("hashCode");
DEFAULT_METHOD_LIST.add("notify");
DEFAULT_METHOD_LIST.add("notifyAll");
DEFAULT_METHOD_LIST.add("toString");
DEFAULT_METHOD_LIST.add("wait");
}

/**
* 实现接口的invoke方法
* @see java.lang.reflect.InvocationHandler.invoke(Object , Method , Object[])
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName() ;
Object result = null ;
ServiceLog.info("开始调用"+object.getClass().getName()+"的方法"+name);
if (DEFAULT_METHOD_LIST.contains(name)) {
result = method.invoke(object , args);
ServiceLog.info("Start : 调用"+object.getClass().getName()+"的方法"+name);
return result ;
} else if (object instanceof OperationService){
//如果代理对象是OperationService实现类,则说明它支持事务处理
OperationService serivce = (OperationService)object ;
TransactionContext tc = factory.getTransactionContext();
try {
serivce.setTransactionContext(tc);
if (name.startsWith("search")) {
//如果是查询方法,则不进行事务封装
result = method.invoke(object , args) ;
} else {
tc.beginTransaction();
try {
result = method.invoke(object , args) ;
tc.commitTransaction();
} catch (Exception ex) {
ServiceLog.error(ex.getMessage() , ex) ;
if (ex instanceof FacadeAccessException) {
FacadeAccessException actual = (FacadeAccessException) ex ;
tc.rollbackTransaction() ;
throw actual ;
}
throw ex ;
}
}
return result ;
} finally {
tc.closeConnection();
ServiceLog.info("End : 调用"+object.getClass().getName()+"的方法"+name);
}

} else {
result = method.invoke(object , args) ;
return result ;
}

}

public Object getObject() {
return object;
}

public void setObject(Object object) {
this.object = object;
}

}
banq

发表文章: 8929
注册时间: 2002年08月03日 17:08
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月13日 19:50 回复
非常不错的动态代理程序,同时使用cache提升了性能。
建议 Proxy.newProxyInstance这一句也采取缓存,每次调用,性能也是比较低的。

建议:BeanConfiguration.SINGLETON.equals(config.getMethod())) 这段if else重整一下,可状态模式,通过辅助类映射XML配置。

这段程序可谓是Spring这个大系统的微观,主体思路非常相似。
凤舞凰扬

发表文章: 26
注册时间: 2004年03月10日 14:25
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月27日 21:56 回复
是啊,说白了,写这程序的思想就是来自于Spring
banq说将Proxy.newInstance也缓存起来,其实开始我也是打算如此,只是后来我发现在处理释放池中的内容时会引来一些问题,带来不必要的耦合。至于将BeanConfiguration.SINGLETON.equals(config.getMethod())) 这段改写,倒是一个不错的主意。
banq

发表文章: 8929
注册时间: 2002年08月03日 17:08
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2004年12月28日 12:29 回复
Jdonframework将Proxy.newInstance进行了缓存处理,缺点是引入了J2EE WEB容器。
fanf

发表文章: 7
注册时间: 2004年11月24日 07:26
为什么不用静态代理呢? 发表: 2005年01月06日 09:45 回复
我觉得没有必要使用动态代理. 静态的代理也能达到同样的效果.可能我对动态代理的特性掌握不够,请教一下在这里使用动态代理有什么好处?谢谢.
这里是静态代理实现:

public class AOPHandler {

static private SamplePortType _orgObject = null;

public static SamplePortType getObject ( ) {
if ( null == _orgObject )
_orgObject = new SamplePortType(){
public void helloWorld(){
SamplePortType obj = SamplePool.getInstance().borrowObject();
obj.helloWorld();
SamplePool.getInstance().returnObject( obj );
}
};

return _orgObject;
}

static public void main ( String args[] ) {
SamplePortType obj = AOPHandler.getObject();
obj.helloWorld ( );
}
}
newPlay

发表文章: 2
注册时间: 2005年01月18日 22:38
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2005年01月18日 22:40 回复
您好:看了许多您发的帖子看是震惊啊。您的技术很佩服啊希望能得到您的指导谢谢呵呵
小弟谢了
newPlay

发表文章: 2
注册时间: 2005年01月18日 22:38
Re: 使用Proxy.newProxyInstance包装对象池,免去returnObject方法调用 发表: 2005年01月18日 22:44 回复
我是对banq说得啊初来乍到理解
这个主题有 18 回复 / 2 页 [ 1 2 下一页 ]
???en_US.forumThreadPrev.name??? 上一主题
Go back to the topic listing   返回主题列表    返回页首  返回页首
???en_US.forumThreadNext.name??? 下一主题
热点TAG: AOP cache DDD EJB 集群 设计模式 Hibernate IOC JiveJdon OO RBAC Spring Struts
查询本论坛内 回复超过的热门帖子
快速发表回复
标题
 
粗体 斜体 下划线 插入图片 插入代码 插入url链接 插入附件
内容
 

解惑之道在J道 ,打造中国最具影响力的的企业软件社区
OpenSource JIVEJDON v3.0 Powered by JdonFramework Code © 2002-07 jdon.com

anti spam