Spring动态代理(一)

动态代理需要一个调用处理程序(invocation handler)来处理方法的调用。调用处理程序是一个简单的类,只需要实现InvocationHandler接口即可。这个接口里只有一个invoke方法,允许你自己控制整个调用过程。下面举例说明:

ArithmeticCalculator

package edu.xaut.jzd.spring;

public interface ArithmeticCalculator {
	public double add(double a,double b);
	public double sub(double a,double b);
	public double mul(double a,double b);
	public double div(double a,double b);
}

ArithmeticCalculatorImpl:

package edu.xaut.jzd.spring;

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

	@Override
	public double add(double a, double b) {
		double result=a+b;
		System.out.println(a+"+"+b+"="+result);
		return result;
	}

	@Override
	public double sub(double a, double b) {
		double result=a-b;
		System.out.println(a+"-"+b+"="+result);
		return result;
	}

	@Override
	public double mul(double a, double b) {
		double result=a*b;
		System.out.println(a+"*"+b+"="+result);
		return result;
	}

	@Override
	public double div(double a, double b) {
		double result=a/b;
		System.out.println(a+"/"+b+"="+result);
		return result;
	}

}


UnitCalculator
package edu.xaut.jzd.spring;

public class UnitCalculatorImpl implements UnitCalculator {

	@Override
	public double kilogramToPound(double kilogram) {
		// TODO Auto-generated method stub
		double pound=kilogram*2.2;
		System.out.println(kilogram+" kilogram= "+pound+" pound");
		return pound;
	}

	@Override
	public double kilometerToMile(double kilometer) {
		// TODO Auto-generated method stub
		double mile=kilometer*0.62;
		System.out.println(kilometer+" kilometer= "+mile+" mile");
		return mile;
	}

}

下面为日志代理和验证代理类:

CalculatorLoggingHandler

package edu.xaut.jzd.spring;

import java.util.Arrays;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class CalculatorLoggingHandler implements InvocationHandler {
	private Log log=LogFactory.getLog(this.getClass());
	
	private Object target;
	
	public CalculatorLoggingHandler(Object target) {
		this.target = target; 
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		log.info("The method "+method.getName()+"() begins with "+Arrays.toString(args));
		Object result=method.invoke(target, args);
		log.info("The method "+method.getName()+"() ends with "+result);
		return result;
	}
	
	public static Object createProxy(Object target){
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(),
				new CalculatorLoggingHandler(target));
	}

}

CalculatorValidationHandler

package edu.xaut.jzd.spring;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CalculatorValidationHandler implements InvocationHandler {
	private Object target;
	
	public CalculatorValidationHandler(Object target) {
		super();
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		for(Object arg:args){
			validate((Double)arg);
		}
		Object result=method.invoke(target, args);
		return result;
	}
	
	private void validate(double a){
		if(a<0){
			throw new IllegalArgumentException("Positive numbers only");
		}
	}

	//创建代理对象
	public static Object createProxy(Object target){
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), 
				new CalculatorValidationHandler(target));
	}
}

下面是Main函数:

package edu.xaut.jzd.spring;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArithmeticCalculator arithmeticCalculatorImpl=new ArithmeticCalculatorImpl();
		ArithmeticCalculator arithmeticCalculator=(ArithmeticCalculator)CalculatorValidationHandler.createProxy(
				CalculatorLoggingHandler.createProxy(arithmeticCalculatorImpl));
		
		arithmeticCalculator.add(1.2, 1.3);
		arithmeticCalculator.sub(1.2, 1.3);
		
		UnitCalculator unitCalculatorImpl=new UnitCalculatorImpl();
		UnitCalculator unitCalculator=(UnitCalculator)CalculatorValidationHandler.createProxy(
				CalculatorLoggingHandler.createProxy(unitCalculatorImpl));
		unitCalculator.kilogramToPound(1);
	}

}

测试输出为:

2012-11-17 9:25:24 edu.xaut.jzd.spring.CalculatorLoggingHandler invoke
信息: The method add() begins with [1.2, 1.3]
2012-11-17 9:25:24 edu.xaut.jzd.spring.CalculatorLoggingHandler invoke
信息: The method add() ends with 2.5
1.2+1.3=2.5
2012-11-17 9:25:24 edu.xaut.jzd.spring.CalculatorLoggingHandler invoke
信息: The method sub() begins with [1.2, 1.3]
1.2-1.3=-0.10000000000000009
2012-11-17 9:25:24 edu.xaut.jzd.spring.CalculatorLoggingHandler invoke
信息: The method sub() ends with -0.10000000000000009
2012-11-17 9:25:24 edu.xaut.jzd.spring.CalculatorLoggingHandler invoke
信息: The method kilogramToPound() begins with [1.0]
1.0 kilogram= 2.2 pound
2012-11-17 9:25:24 edu.xaut.jzd.spring.CalculatorLoggingHandler invoke
信息: The method kilogramToPound() ends with 2.2
要创建一个具有调用处理程序的动态代理实例,就须调用静态方法Proxy.newProxyInstance().

这个方法的第一个参数是ClassLoader,负责注册该代理。第二个参数由该代理需要实现的接口组成,通常需要代理目标类的所有接口。最后一个参数是处理方法调用的调用处理程序。

在Main类里,可以使用验证代理包装日志代理形成一个代理链。所有计算器方法的调用都先要经过验证代理,再经过日志代理。这意味着验证先于日志执行。如要调换顺序,则用日志代理包装验证代理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值