本文目录一览:
- 1、Java程序性能优化-代理模式(5)
- 2、Java设计模式之Proxy模式
- 3、Java代理的作用和实现?
- 4、Java静态代理和iOS代理模式这两个概念的理解上的疑惑
- 5、java中的代理是什么意思?
Java程序性能优化-代理模式(5)
代理模式( )
在以上代码中 使用CtField make()方法和CtNewMehod make()方法在运行时生成了代理类的字段和方法 这些逻辑由Javassist的CtClass对象处理 将Java代码转换为对应的字节码 并生成动态代理类的实例
注意 与静态代理相比 动态代理可以很大幅度地减少代码行数 并提升系统的灵活性
在Java中 动态代理类的生成主要涉及对ClassLoader的使用 这里以CGLIB为例 简要阐述动态类的加载过程 使用CGLIB生成动态代理 首先需要生成Enhancer类实例 并指定用于处理代理业务的回调类 在Enhancer create()方法中 会使用DefaultGeneratorStrategy Generate()方法生成动态代理类的字节码 并保存在byte数组中 接着使用ReflectUtils defineClass()方法 通过反射 调用ClassLoader defineClass()方法 将字节码装载到ClassLoader中 完成类的加载 最后使用ReflectUtils newInstance()方法 通过反射 生成动态类的实例 并返回该实例 无论使用何种方法生成动态代理 虽然实现细节不同 但主要逻辑都如图 所示
图 实现动态代理的基本步骤
前文介绍的几种动态代理的生成方法 性能有一定差异 为了能更好地测试它们的性能 去掉DBQuery类中的sleep()代码 并使用以下方法测试
public static final int CIRCLE= ;
public static void main(String[] args) throws Exception {
IDBQuery d=null;
long begin=System currentTimeMillis()
d=createJdkProxy() //测试JDK动态代理
System out println( createJdkProxy: +(System currentTimeMillis() beg in))
System out println( JdkProxy class: +d getClass() getName())
begin=System currentTimeMillis()
for(int i= ;iCIRCLE;i++)
d request()
System out println( callJdkProxy: +(System currentTimeMillis() begin ))
begin=System currentTimeMillis()
d=createCglibProxy() //测试CGLIB动态代理
System out println( createCglibProxy: +(System currentTimeMillis() b egin))
System out println( CglibProxy class: +d getClass() getName())
begin=System currentTimeMillis()
for(int i= ;iCIRCLE;i++)
d request()
System out println( callCglibProxy: +(System currentTimeMillis() beg in))
begin=System currentTimeMillis()
d=createJavassistDynProxy() //测试Javaassist动态代理
System out println( createJavassistDynProxy: +(System currentTimeMil lis() begin))
System out println( JavassistDynProxy class: +d getClass() getName())
begin=System currentTimeMillis()
for(int i= ;iCIRCLE;i++)
d request()
System out println( callJavassistDynProxy: +(System currentTimeMilli s() begin))
begin=System currentTimeMillis()
d=createJavassistBytecodeDynamicProxy() //测试Javassist动态代理
System out println( createJavassistBytecodeDynamicProxy: +(System cu rrentTimeMillis() begin))
System out println( JavassistBytecodeDynamicProxy class: +d getClass()
getName())
begin=System currentTimeMillis()
for(int i= ;iCIRCLE;i++)
d request()
System out println( callJavassistBytecodeDynamicProxy: +(System curr entTimeMillis() begin))
}
返回目录 Java程序性能优化 让你的Java程序更快 更稳定
编辑推荐
Java程序设计培训视频教程
J EE高级框架实战培训视频教程
J ME移动开发实战教学视频
Visual C++音频/视频技术开发与实战
Oracle索引技术
lishixinzhi/Article/program/Java/gj/201311/27830
Java设计模式之Proxy模式
为什么要使用Proxy?
授权机制 不同级别的用户对同一对象拥有不同的访问权利 如Jive 论坛系统中 就使用Proxy 进行授权机制控制 访问论坛有两种人:注册用户和游客(未注册用户) Jive 中就通过类似ForumProxy 这样的代理来控制这两种用户对论坛的访问权限
某个客户端不能直接操作到某个对象 但又必须和那个对象有所互动
举例两个具体情况:
( )如果那个对象是一个是很大的图片 需要花费很长时间才能显示出来 那么当这个图片包含在文档中时 使用编辑器或浏览器打开这个文档 打开文档必须很迅速 不能等待大图片处理完成 这时需要做个图片Proxy 来代替真正的图片
( )如果那个对象在Internet 的某个远端服务器上 直接操作这个对象因为网络速度原因可能比较慢 那我们可以先用Proxy 来代替那个对象
总之原则是 对于开销很大的对象 只有在使用它时才创建 这个原则可以为我们节省很多宝贵的Java 内存 所以 有些人认为Java 耗费资源内存 我以为这和程序编制思路也有一定的关系
如何使用Proxy?
以Jive 论坛系统为例 访问论坛系统的用户有多种类型:注册普通用户 论坛管理者 系统管理者 游客 注册普通用户才能发言;论坛管理者可以管理他被授权的论坛;系统管理者可以管理所有事务等 这些权限划分和管理是使用Proxy 完成的
Forum 是Jive 的核心接口 在Forum 中陈列了有关论坛操作的主要行为 如论坛名称 论坛描述的获取和修改 帖子发表删除编辑等
在ForumPermissions 中定义了各种级别权限的用户:
public class ForumPermissions implements Cacheable {
/*** Permission to read object */
public static final int READ = ;
/*** Permission to administer the entire sytem */
public static final int SYSTEM_ADMIN = ;
/*** Permission to administer a particular forum */
public static final int FORUM_ADMIN = ;
/*** Permission to administer a particular user */
public static final int USER_ADMIN = ;
/*** Permission to administer a particular group */
public static final int GROUP_ADMIN = ;
/*** Permission to moderate threads */
public static final int MODERATE_THREADS = ;
/*** Permission to create a new thread */
public static final int CREATE_THREAD = ;
/*** Permission to create a new message */
public static final int CREATE_MESSAGE = ;
/*** Permission to moderate messages */
public static final int MODERATE_MESSAGES = ;
public boolean isSystemOrForumAdmin() {
return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);
}
}
因此 Forum 中各种操作权限是和ForumPermissions 定义的用户级别有关系的 作为接口Forum 的实现:ForumProxy 正是将这种对应关系联系起来 比如 修改Forum 的名称 只有论坛管理者或系统管理者可以修改 代码如下:
public class ForumProxy implements Forum {
private ForumPermissions permissions;
private Forum forum;
this authorization = authorization;
public ForumProxy(Forum forum Authorization authorization
ForumPermissions permissions)
{
this forum = forum;
this authorization = authorization;
this permissions = permissions;
}
public void setName(String name) throws UnauthorizedException
ForumAlreadyExistsException
{
//只有是系统或论坛管理者才可以修改名称
if (permissions isSystemOrForumAdmin()) {
forum setName(name);
}
else {
throw new UnauthorizedException();
}
}
}
而DbForum 才是接口Forum 的真正实现 以修改论坛名称为例:
public class DbForum implements Forum Cacheable {
public void setName(String name) throws
ForumAlreadyExistsException {
this name = name;
//这里真正将新名称保存到数据库中
saveToDb();
}
}
凡是涉及到对论坛名称修改这一事件 其他程序都首先得和ForumProxy 打交道 由ForumProxy 决定是否有权限做某一样事情 ForumProxy 是个名副其实的 网关 安全代理系统
我们已经知道 使用Forum 需要通过ForumProxy Jive 中创建一个Forum 是使用Factory 模式 有一个总的抽象类ForumFactory 在这个抽象类中 调用ForumFactory 是通过getInstance()方法实现 这里使用了Singleton getInstance()返回的是ForumFactoryProxy
为什么不返回ForumFactory 而返回ForumFactory 的实现ForumFactoryProxy?
原因是明显的 需要通过代理确定是否有权限创建forum
在ForumFactoryProxy 中我们看到代码如下:
public class ForumFactoryProxy extends ForumFactory {
protected ForumFactory factory;
protected Authorization authorization;
protected ForumPermissions permissions;
public ForumFactoryProxy(Authorization authorization ForumFactory factory
ForumPermissions permissions)
{
this factory = factory;
this authorization = authorization;
this permissions = permissions;
}
public Forum createForum(String name String description)
throws UnauthorizedException ForumAlreadyExistsException
{
//只有系统管理者才可以创建forum
if (permissions get(ForumPermissions SYSTEM_ADMIN)) {
Forum newForum = factory createForum(name description);
return new ForumProxy(newForum authorization permissions);
}
else {
throw new UnauthorizedException();
}
}
方法createForum 返回的也是ForumProxy Proxy 就象一道墙 其他程序只能和Proxy 交互操作
注意到这里有两个Proxy:ForumProxy 和ForumFactoryProxy 代表两个不同的职责:使用Forum 和创建Forum;
至于为什么将使用对象和创建对象分开 这也是为什么使用Factory 模式的原因所在:是为了 封装 分派 ;换句话说 尽可能功能单一化 方便维护修改
以上我们讨论了如何使用Proxy 进行授权机制的访问 Proxy 还可以对用户隐藏另外一种称为copy on write 的优化方式 拷贝一个庞大而复杂的对象是一个开销很大的操作 如果拷贝过程中 没有对原来的对象有所修改 那么这样的拷贝开销就没有必要 用代理延迟这一拷贝过程
比如:我们有一个很大的Collection 具体如hashtable 有很多客户端会并发同时访问它
其中一个特别的客户端要进行连续的数据获取 此时要求其他客户端不能再向hashtable 中增加或删除 东东
最直接的解决方案是:使用collection 的lock 让这特别的客户端获得这个lock 进行连续的数据获取 然后再释放lock
public void foFetches(Hashtable ht){
synchronized(ht){
//具体的连续数据获取动作
}
}
但是这一办法可能锁住Collection 会很长时间 这段时间 其他客户端就不能访问该Collection 了
第二个解决方案是clone 这个Collection 然后让连续的数据获取针对clone 出来的那个Collection 操作 这个方案前提是 这个Collection 是可clone 的 而且必须有提供深度clone 的方法 Hashtable 就提供了对自己的clone 方法 但不是Key 和value 对象的clone 关于Clone 含义可以参考专门文章
public void foFetches(Hashtable ht){
Hashttable newht=(Hashtable)ht clone();
}
问题又来了 由于是针对clone 出来的对象操作 如果原来的母体被其他客户端操作修改了 那么对clone 出来的对象操作就没有意义了
最后解决方案:我们可以等其他客户端修改完成后再进行clone 也就是说 这个特别的客户端先通过调用一个叫clone 的方法来进行一系列数据获取操作 但实际上没有真正的进行对象拷贝 直至有其他客户端修改了这个对象Collection
lishixinzhi/Article/program/Java/gj/201311/27422
Java代理的作用和实现?
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
Java静态代理和iOS代理模式这两个概念的理解上的疑惑
看了JAVA版的设计模式的 代理模式 和IOS @protrol 比较,java 的看了都晕了。不完全一致,委托和代理 称呼上就好像反的。用JAVA 的中接口 在view中实现方法,就要把接口中所有的方法都复写一下,这个不太好用, 还不知道其它什么模式来实现像Ios @protrol 的功能。
java中的代理是什么意思?
代理模式在设计模式中的定义就是:为其他对象提供一种代理以控制对这个对象的访问。说白了就是,在一些情况下客户不想或者不能直接引用一个对象,而代理对象可以在客户和目标对象之间起到中介作用,去掉客户不能看到的内容和服务或者增添客户需要的额外服务。