首页 > 代码库 > 动态代理

动态代理

1:首先代理是一种常用的设计模式,其目的就是为其它对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息转发消息,以及进行消息被委托执行后的后续处理。程序中的代理是:要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码!


代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象.任何对原始对象的调用都要通过代理.代理对象决定是否以及何时将方法调用转到原始对象上。



2:接口:

public interface ArithmetricCalculator {

	int add (int i , int j);
	int sub (int i , int j);
	int mul (int i , int j);
	int div (int i , int j);
}

3:实现类:

public class ArithmetricCalculatorImpl implements ArithmetricCalculator {

	@Override
	public int add(int i, int j) {
		int result = i + j;
		return result;
	}

	@Override
	public int sub(int i, int j) {
		int result = i - j;
		return result;
	}

	@Override
	public int mul(int i, int j) {
		int result = i * j;
		return result;
	}

	@Override
	public int div(int i, int j) {
		int result = i / j;
		return result;
	}
}

4:代理类:

其功能主要是在实现类中的每个方法中增加日志管理的相关功能!

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/***
 * 本程序的功能:演示动态代理
 * @author Shiyeqiang
 *
 */
public class ArithmetricCalculatorLoggingProxy {
	
	/**
	 * 要代理的对象,实际上是一个接口
	 */
	ArithmetricCalculator target;
	public ArithmetricCalculatorLoggingProxy(ArithmetricCalculator target) {
		super();
		this.target = target;
	}
	/**
	 * 表示要返回的代理对象
	 * 
	 */
	public ArithmetricCalculator getLoggingProxy(){
		
		ArithmetricCalculator proxy=null;
		
		ClassLoader loader=ArithmetricCalculator.class.getClassLoader();
		
		Class [] interfaces = new Class[]{ArithmetricCalculator.class};
		
		InvocationHandler h=new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				System.out.println("the Method"+method.getName()+"before"+Arrays.asList(args));
				Object result=null;
				result=method.invoke(target, args);
				System.out.println("the Method"+method.getName()+"result:"+result);
				return result;
			}
		};
		/**
		 * loader:代理对象使用的类加载器
		 * interfaces:指定代理对象的类型. 即代理代理对象中可以有哪些方法. 
		 * h: 当具体调用代理对象的方法时, 应该如何进行响应, 实际上就是调用 InvocationHandler 的 invoke 方法
		 */
		proxy=(ArithmetricCalculator) Proxy.newProxyInstance(loader, interfaces, h);
		return proxy;
	}
}

知识点讲解:

newProxyInstance

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
                               throws IllegalArgumentException
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。此方法相当于:
     Proxy.getProxyClass(loader, interfaces).
         getConstructor(new Class[] { InvocationHandler.class }).
         newInstance(new Object[] { handler });
 

Proxy.newProxyInstance 抛出 IllegalArgumentException,原因与Proxy.getProxyClass 相同。

参数:
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
返回:
一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
抛出:
IllegalArgumentException - 如果违反传递到getProxyClass 的参数上的任何限制
NullPointerException - 如果interfaces 数组参数或其任何元素为null,或如果调用处理程序 hnull

5:客户端代码:

public static void main(String[] args) {
		
		ArithmetricCalculator arithmetricCalculator=new ArithmetricCalculatorImpl();
		arithmetricCalculator=new ArithmetricCalculatorLoggingProxy(arithmetricCalculator).getLoggingProxy();
		
		int res=arithmetricCalculator.add(1, 2);
		System.out.println(res);
		
		res=arithmetricCalculator.div(4, 2);
		System.out.println(res);
		
		
	}




动态代理