代理模式——动态代理(JDK与CGlib)

静态代理

看如下例子:
ICalculatorService 接口中代码如下

package com.jd.calculator;

public interface ICalculatorService {

	//接口中的抽象方法,在CalculatorService中实现接口中的方法。
	int add(int a, int b);
	int sub(int a, int b);
	int mul(int a, int b);
	int div(int a, int b);
}

CalculatorService 实现了ICalculatorService 接口

package com.jd.calculator;

public class CalculatorService implements ICalculatorService {

	@Override
	public int add(int a, int b) {
		System.out.println(this.getClass().getName()+":The add method begins.");
		System.out.println(this.getClass().getName()+":Parameters of the add method: ["+a+","+b+"]");
		int result = a+b;
		System.out.println(this.getClass().getName()+":Result of the add method:"+result);
		System.out.println(this.getClass().getName()+":The add method ends.");
		return result;
	}

	@Override
	public int sub(int a, int b) {
		System.out.println(this.getClass().getName()+":The sub method begins.");
		System.out.println(this.getClass().getName()+":Parameters of the sub method: ["+a+","+b+"]");
		int result = a-b;
		System.out.println(this.getClass().getName()+":Result of the sub method:"+result);
		System.out.println(this.getClass().getName()+":The sub method ends.");
		return result;
	}

	@Override
	public int mul(int a, int b) {
		System.out.println(this.getClass().getName()+":The mul method begins.");
		System.out.println(this.getClass().getName()+":Parameters of the mul method: ["+a+","+b+"]");
		int result = a*b;
		System.out.println(this.getClass().getName()+":Result of the mul method:"+result);
		System.out.println(this.getClass().getName()+":The mul method ends.");
		return result;
	}

	@Override
	public int div(int a, int b) {
		System.out.println(this.getClass().getName()+":The div method begins.");
		System.out.println(this.getClass().getName()+":Parameters of the div method: ["+a+","+b+"]");
		int result = a/b;
		System.out.println(this.getClass().getName()+":Result of the div method:"+result);
		System.out.println(this.getClass().getName()+":The div method ends.");
		return result;
	}
}

Test中对上述代码进行操作:

package com.jd.test;
public class Test {

	public static void main(String[] args) {
		//简单的调用
		CalculatorService calculatorService=new CalculatorService();
		int result=calculatorService.add(2,3);
		System.out.println(result);
	}
}

输出如下结果:

我们可以看到,不论调用哪个方法,都会输出除了结果之外的四行代码,怎么样实现代码的复用,达到简化代码的效果?

动态代理(JDK)

下边用动态代理的方法实现简化代码:仅以检验add方法为例。
ICalculatorService 接口中代码如下

package com.jd.calculator;

public interface ICalculatorService {
	int add(int a, int b);
}

CalculatorService中代码如下,实现了ICalculatorService 接口

package com.jd.calculator;

public class CalculatorService implements ICalculatorService {

	@Override
	public int add(int a, int b) {
		int result = a+b;
		return result;
	}
}

Test中代码如下:

package com.jd.test;

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

import com.jd.calculator.CalculatorService;
import com.jd.calculator.ICalculatorService;
import com.jd.calculator.ProxyFactory;

public class Test {

	public static void main(String[] args) {

		//动态代理的方法实现代码的复用。
		System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");//打印临时类文件代码。
		
		CalculatorService calculatorService=new CalculatorService();
		
		InvocationHandler handler=new InvocationHandler(){//匿名内部类对象

			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//proxy为代理,method为要使用的方法,args为参数列表。
				String name=method.getName();//获取要使用的方法名字。
				System.out.println(calculatorService.getClass().getName()+":The "+name+" method begins.");
				System.out.println(calculatorService.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
				Object result = method.invoke(calculatorService, args);//调用目标对象,即目标方法,此处为add方法。	//等价于calculatorService.add(args);
				System.out.println(calculatorService.getClass().getName()+":Result of the "+name+" method:"+result);
				System.out.println(calculatorService.getClass().getName()+":The "+name+" method ends.");
				return result;
			}
		};
		
		//ClassLoader classLoader=CalculatorService.class.getClassLoader();//类加载过程,实现相同的类加载。
		ICalculatorService cService=(ICalculatorService) Proxy.newProxyInstance(calculatorService.getClass().getClassLoader(), calculatorService.getClass().getInterfaces(), handler);//1,用反射的方法创建动态代理;2,实现接口(与CalculatorService实现的相同);3,具体做什么。
		int result=cService.add(3, 4);
		System.out.println(result);
	}
}

输出结果如下:

下边详述Test中代码执行过程:
先说明每一步代码的作用:

package com.jd.test;

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

import com.jd.calculator.CalculatorService;
import com.jd.calculator.ICalculatorService;
import com.jd.calculator.ProxyFactory;

public class Test {

	public static void main(String[] args) {
		System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");//打印临时类文件代码。
		CalculatorService calculatorService=new CalculatorService();//创建calculatorService对象。
		
		InvocationHandler handler=new InvocationHandler(){//匿名内部类对象,直接调用invoke方法

			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//proxy为代理,method为要使用的方法,args为参数列表。
				String name=method.getName();//获取要使用的方法名字。
				System.out.println(calculatorService.getClass().getName()+":The "+name+" method begins.");
				System.out.println(calculatorService.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
				Object result = method.invoke(calculatorService, args);//调用目标对象,即目标方法,此处为add方法。	//等价于calculatorService.add(args);
				System.out.println(calculatorService.getClass().getName()+":Result of the "+name+" method:"+result);
				System.out.println(calculatorService.getClass().getName()+":The "+name+" method ends.");
				return result;
			}
		};
		
		ICalculatorService cService=(ICalculatorService) Proxy.newProxyInstance(calculatorService.getClass().getClassLoader(), calculatorService.getClass().getInterfaces(), handler);//各个变量具体含义为:1),用反射的方法创建动态代理;2),实现接口(与CalculatorService实现的相同);3),具体做什么。
		int result=cService.add(3, 4);//cService存的是由Proxy创建的实现了ICalculatorService的一个内部类,cService.add(arg,arg)其实是调用了由Proxy创建的匿名内部类对象中的add方法。
		System.out.println(result);
	}
}

内部类 $Proxy0 继承自 Proxy 实现了 ICalculatorService,所以实现了add方法。
代码执行过程为:创建了CalculatorService对象——》Proxy调用newProxyInstance方法得到Object对象,所以下转型,得到内部类对象 $Proxy0 ,实现了接口,所以重写了接口中的抽象方法——》handler为匿名内部类对象,直接调用invoke方法——》执行Object result = method.invoke(calculatorService, args);此行代码,调用add方法int result=cService.add(3, 4);传值——》返回结果——》输出结果。
接下来对上述代理模式进行简单的封装
创建一个ProxyFactory(代理工厂)类:

package com.jd.calculator;

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

public class ProxyFactory {

	static CalculatorService target;
	
	static InvocationHandler handler=new InvocationHandler(){//匿名内部类对象

		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//proxy为代理,method为要使用的方法,args为参数。
			String name=method.getName();//获取要使用的方法名字。
			System.out.println(target.getClass().getName()+":The "+name+" method begins.");
			System.out.println(target.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
			
			Object result = method.invoke(target, args);//调用目标对象,即目标方法。
			
			System.out.println(target.getClass().getName()+":Result of the "+name+" method:"+result);
			System.out.println(target.getClass().getName()+":The "+name+" method ends.");
			return result;
		}
	};
	
	public static Object getProxy(CalculatorService target) {
		ProxyFactory.target=target;//将传入的参数赋给成员变量,this.target=target;亦可以。
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
	}
}

Test中代码如下

package com.jd.test;

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

import com.jd.calculator.CalculatorService;
import com.jd.calculator.ICalculatorService;
import com.jd.calculator.ProxyFactory;

public class Test {

	public static void main(String[] args) {
    	System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
		ICalculatorService calculatorService=(ICalculatorService)ProxyFactory.getProxy(new CalculatorService());//用反射的方法创建动态代理,实现接口(与CalculatorService实现的相同),干什么活
		int result=calculatorService.add(3, 4);
		System.out.println(result);
	}
}

proxy继承自Proxy,实现了ICalculatorService 接口

动态代理(CGlib)

ICalculatorService,CalculatorService中代码与 动态代理(JDK)中相同。
目录如下
在这里插入图片描述
ProxyFactory 中代码如下

package com.zzu.calculator;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ProxyFactory {

	static CalculatorService target;//目标对象
	
	static Callback callback=new MethodInterceptor(){//匿名内部类对象

		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			String name=method.getName();//获取要使用的方法名字。
			System.out.println(target.getClass().getName()+":The "+name+" method begins.");
			System.out.println(target.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
			System.out.println(proxy.getClass().getSuperclass());
			
			Object result = method.invoke(target, args);//调用目标对象,即目标方法。
			
			System.out.println(target.getClass().getName()+":Result of the "+name+" method:"+result);
			System.out.println(target.getClass().getName()+":The "+name+" method ends.");
			return result;
		}
	};
	
	public static Object getProxy(CalculatorService target) {
		ProxyFactory.target=target;//将传入的参数赋给成员变量
		Enhancer enhancer=new Enhancer();
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(callback);
		return enhancer.create();
	}
}

Test中代码如下
在这里插入图片描述
proxy直接继承自CalculatorService
运行结果如下:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值