【菜鸟学Java】13:代理模式——动态代理这样玩!

        在上篇博客中,我们说到了代理模式的一种形式——静态代理,文章结尾处提到了静态代理的不足之处,其中有一个就是当我们的业务类非常多的时候,还用静态代理显然是一个非常糟糕的选择,那么这种情况该如何解决呢?这就引出了我们的动态代理。

        什么是动态代理?

        所谓的动态代理是相对于静态代理来讲的,利用反射机制,在程序的运行期决定加载哪个类,很好的规避了静态代理一个业务类对应一个代理类的问题。

        为何用动态代理?

        使用动态代理是为了解决静态代理的扩展性差和维护困难的问题,这个在文章开头就说的很明白了,

        如何用动态代理?

        要想使用动态代理,就必须使用Proxy(代理类)和InvocationHandler(反射)两个东西了。我接着使用上篇博客的例子为大家说明如何使用动态代理。

        用户管理的接口和实现就不再赘述了,下面请直接看动态代理类LogHandler和客户端的代码:

        模拟日志功能的动态代理对象类LogHandler。代码如下:

public class LogHandler implements InvocationHandler {
	
	//目标对象
	private Object targetObject;
	
	/**
	 * 该类的实例化方法,用于将目标对象传入
	 * @param targetObject  目标对象
	 * @return
	 */
	public Object newProxyInstance(Object targetObject) {
		
		this.targetObject = targetObject;
		
		//调用Proxy类的静态方法newProxyInstance实例化一个代理类,并且将目标对象作为参数传入
		return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
							   targetObject.getClass().getInterfaces(), this);
	}
	/**
	 * 执行目标对象的方法
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		
		//在目标对象的方法执行之前打印一下
		System.out.println("开始执行方法-->>" + method.getName());
		
		for (int i=0; i<args.length; i++) {
			System.out.println(args[i]);
		}
		Object ret = null;
		try {
			
			//调用目标对象的方法
			ret = method.invoke(targetObject, args);
			
			//在目标对象的方法执行之后打印一下
			System.out.println("方法执行完毕!-->>" + method.getName()); 
		}catch(Exception e) {
			e.printStackTrace();
			System.out.println("方法执行出错!-->>" + method.getName());
			throw e;
		}
		return ret;
	}

}

        客户端:

public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		//实例化动态代理类LogHandler
		LogHandler logHandler = new LogHandler();
		
		//将用户管理实现类传入动态代理类
		UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl());
		//userManager.addUser("0001", "钟跃民");
		//userManager.delUser("0001");
		String name = userManager.findUser("0001");
		System.out.println("Client.main() --- " + name);
	}

}

        小结一下:

        动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强。

        无论是静态代理和是动态代理,这种代理的思想,是十分有指导意义的。很多的框架和技术,都有代理的影子。比如Spring中的AOP(面向切面编程)的本质就是代理模式,还有SSH框架中的每一个框架都使用了代理模式。

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
    从前几次老师的讲课中我们能看UML对我们重要性。一开始真是懵懵懂懂的,搞不懂为什么一个UML图有这么大的价值。从开始了合作版机房才听说可以用类图和包图生成整个系统的框架,然后只需要完成其中的一些方法就好了。听起来好高大上的样子,一方面是想多多尝试新鲜的东西,另一方面是想偷懒啊。 抱这样的心态就开始了。 1、设定编写语言     主要是类图用来生成代码。首先是要先给类图设定好语言。机房合作我们用C#开发所以就是:工具——选项——代码工程——代码默认语言——C#详细见图。              
造成这个问题的原因大多数是因为非正常关机后导致文件系统受损引起的,在系统重启之后,受损分区就会被Linux自动挂载为只读。解决的方法是通过fsck来修复文件系统,然后重启即可,以下是以针对/dev/xvde1分区,ext4文件系统分区的一个操作案例: fsck.ext4 -y /dev/xvde1 本文只着重强调一点:要针对出问题的分区进行操作,在挂载了多个硬盘的机器上要仔细分辨一下。
前言 HDFS也可以支持Erasure Coding功能了,将会在Hadoop 3.0中发布,可以凭图为证: 在 HDFS-7285 中,实现了这个新功能.鉴于此功能还远没有到发布的阶段,可能后面此块相关的代码还会进行进一步的改造,因此只是做一个所谓的 预分析 ,帮助大家提前了解Hadoop社区目前是如何实现这一功能的.本人之前也没有接触过Erasure Coding技术,中间过程也确实有些偶然,相信本文可以带给大家收获. 巧遇Hadoop 3.0 Erasure Coding 第一次主动去了解erasu
OA提供对微信的支持这一点做的非常好,用户使用起来也更方便了。 而其中的个别功能还有待完善,比如今天要说的这个微信查询用户信息模块。升级前的使用方法:输入@+用户中文名,并且要求完全匹配,然而在实际使用中用户反馈当出现重名时,只能查询到一个用户,其他用户的数据是查不出来的。 原来版本查询是这个样子的: 基于上面的设计,当时的处理办法是把重名用户后面再加上数字加以区分,然而这样的方案并不完美。 今天,在这个功能上进行了些升级改造,改造后可以进行模糊查询,对于相似的用户可以全部列出,避免了完全记忆的麻烦。为了
一、常用命令 ls 显示文件或目录 -l 列出文件详细信息l(list) -a 列出当前目录下所有文件及目录,包括隐藏的a(all) ll 会列出该文件下的所有文件信息,包括隐藏的文件的文件详细信息,使用ls -l -a也可以达到同样效果 mkdir 创建目录 -p 创建目录,若无父目录,则创建p(parent) cd 切换目录 touch 创建空文件 cat 查看文件内容 more、less 分页显示文本文件内容(与cat不同,cat是显示全部内容) cp 拷贝 mv 移动或重命名 rm 删除文件或目录
         什么是静态代理?         周所周知,常用的23种设计模式中,有一个代理模式(Proxy Pattern)。它的定义如下:         为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。         代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信。         那么静态代理又是什么鬼呢
nginx很早就支持tcp proxy,但是一直不知道其使用,最近在nginx blog上看见了,一些实践者将其运用到数据库访问的负载均衡以及实现读写分离,来提高数据库的吞吐量,这里我不会讲具体的搭建实现,只是最一些理论上的设计猜想。 直接上图 db集群,分为读db和写db,写db向读db同步数据。读db只能读,写db只能写,图中读写各一个,只是一个例子,实际需要根据业务来配置读写服务器比例。 nginx tcp proxy实现读写分离,提供只读的端口和只写的端口。 db connection pool维

Shell脚本了解 - 2016-02-27 17:02:11

一、什么是Shell Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。 Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。 Ken Thompson的sh是第一种Unix Shell,Windows Explorer是一个典型的图形界面Shell。 二、Shell 脚本 Shell 脚本(shell script),是一种为shell编写的脚本程序。 业界所说的shell通常都是指shel
博主的linux是ubuntu 14.04.3。 在安装apache最新版httpd-2.4.3的时候遇到各种坑。 先提供安装apache httpd-2.4.3所需要的包,博主已经整理好,下载地址: http://download.csdn.net/download/u013142781/9445609 里面包含了: apache 安装包:httpd-2.4.3.tar.gz 依赖的包:apr-1.4.6.tar.gz、apr-util-1.4.1.tar.gz、pcre-8.20.tar.bz2 一开

Solr基础教程之Query(四) - 2016-02-26 17:02:02

前面介绍了各种配置,以及查询语法,这里通过图形界面,简单的讲解一下solr的查询。 仅通过截图来介绍一些最基本的用法: 首先打开主界面,点击Query 直接点击Excute Query按钮 输入条件q进行查询 使用fq进行查询,注意这里的keyword是用来检索的字段,他包含name、address、gender、expert_skill,这几个属性,所以我搜索“海”能够查询出来有海字的记录 使用sort排序 使用start和rows,一般是分页的时候使用的 使用fl决定查询哪些字段 df – 默认的查询