java中的代理和动态代理讲解

在说到动态代理模式,我们首先说一说什么是代理模式。

 

什么是代理模式:

Proxy Pattern(即:代理模式),23种常用的面向对象软件的设计模式之一

代理模式的定义:这里先举一个例子,假设某人要找对象,但是由于某些原因不能直接去找,于是委托一个中介机构去完成这一过程,如婚姻介绍所,在这里婚姻介绍所其实就是一个代理。再举一个专业相关的例子,如果你想调用一个功能非常强大的加密算法,而现在正在开发的系统又需要使用到该算法,由于该算法位于远程服务器端,封装该算法的对象位于远程服务器内存中,本地内存中的对象无法直接访问,因此需要通过一个远程代理的机制来实现远程对象的操作。也其实也就是webservice、httpclient等实现原理。再看代理的定义:给某一个对象提供一个代理,并有代理对象控制对原对象的引用。

优点:

  • 职责清晰 :真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
  • 代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。
  • 增强代码的拓展性

结构

一个是真正的你要访问的对象(目标类),另一个是代理对象,真正对象与代理对象实现同一个接口。先访问代理类并通过代理对象来访问真正要访问的对象中的方法。

 

简单案例

在一个论坛中已注册用户和游客的权限不同个,已注册的用户拥有发帖、修改自己的注册信息、修改自己的帖子等功能;而游客只能看到别人发的帖子,没有其他权限。在这里我们使用代理模式来设计权限管理模块。

抽象主题类

public interface AbstractDemo {
	
	public void function();
	

}

AbstractDemo作为抽象权限类,充当了抽象主体角色,在其中声明了真实主题角色所提供的业务方法,它是真是主题角色和代理主题角色的公共接口。这里所说的主题角色就是需要被代理的对象

真实主题类(需要被代理的类)

public class RealDemo implements AbstractDemo {

	@Override
	public void function() {

		System.out.println("一种算法");
	}

RealDemo是真实主题角色,它实现了在抽象主题角色中定义的方法,假设由于种种原因,客户端无法直接访问其中的方法。

代理主题角色

public class DemoProxy implements AbstractDemo {
	
	private RealDemo demo = new RealDemo();
	@Override
	public void function() {
		demo.function();
	}

}

这样我们就用DemoProxy代理了RealDemo,并使用了RealDemo的function方法。

客户端调用 

public static void main(String[] args) {
		
	AbstractDemo demo = new DemoProxy();
	demo.function();
}

 

动态代理模式

在上述的代理模式不知道大家有没有注意到一些问题,1、就是如果DemoProxy要想调用RealDemo中的function方法,首先这个真实主题角色也就是RealDemo必须存在。2、如果一个真实角色对应一个代理主题角色,这将导致系统中类的数量急剧增加。上述两个问题都是动态代理需要解决的问题。

接下来我们重复代理模式的过程,看看动态代理是怎样解决的

抽象主题类

package demo;

public interface AbstractDemo {
	
	public void function(int i);
}

真实主题类一(需要被代理的类)

public class RealDemo1 implements AbstractDemo {

	@Override
	public void function(int i) {
		
		System.out.println("一种加密算法"+i);
	}

}

真实主题类二(需要被代理的类)

public class RealDemo2 implements AbstractDemo {

	@Override
	public void function(int i) {
		
		System.out.println("一种解密算法"+i);
	}

}

动态代理的实现过程

class TestDemo {

	public static void main(String[] args) {
		
		final AbstractDemo demo1 = new RealDemo1();
//		Proxy.newProxyInstance():产生代理类的实例。仅能代理实现至少一个接口的类
//		ClassLoader:类加载器。也可以写成demo.getClass().getClassLoader()。
//		Class[] interface:代理类要实现的接口。固定写法,和被代理类使用相同的接口即可。
//		InvocationHandler:策略(方案)设计模式的应用。如何代理?
		AbstractDemo proxy = (AbstractDemo)Proxy.newProxyInstance(AbstractDemo.class.getClassLoader(), 
				new Class[]{AbstractDemo.class}, new InvocationHandler() {
//			  InvocationHandler中的invoke方法:调用代理类的任何方法,此方法都会执行	
//			  Object proxy:代理对象本身的引用。一般用不着。
//			  Method method:当前调用的方法。
//			  Object[] args:当前方法用到的参数				
					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						System.out.println("执行方法前");
						Object obj =  method.invoke(demo1,new Object[]{(int)args[0]});
						System.out.println("执行方法后");
						return obj;
					}
				});
		proxy.function(2);
	}
}

结果如下:

执行方法前
一种算法2
执行方法后


上面代码的注解非常详细,如果大家认真阅读,应该对动态代理应该明白的差不多了。阅读上面代码,动态代理可以动态地代理你说需要代理的对象,这里我们代理的是RealDemo1对象。如果我们想代理RealDemo2对象,那么我们只要首先实例RealDemo2对象,得到demo2,然后method.invoke(demo1,new Object[]{args[0]});中的demo1改成demo2即可。这样这个动态代理就可以代理很多主题类,那么系统的类就不会急剧增加了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值