java设计模式:代理模式

代理模式

定义:为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。


平时讲的代理主要指的是智能引用代理,它又有两种实现方式:静态代理和动态代理。

静态代理:

代理和被代理对象在代理之前是确定的,他们都继承相同的抽象类或实现相同的接口。且一般都是使用聚合的方式来实现。

moveable接口

public interface Moveable {
	void move();
}

Car类

public class Car implements Moveable {
	@Override
	public void move() {
		
		try {
			Thread.sleep(new Random().nextInt(1000));
			System.out.println("汽车行驶中.....");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

TimeProxy记录行驶时间代理类

public class TimeProxy implements Moveable {

	private Moveable car;

	
	public TimeProxy(Moveable car) {
		super();
		this.car = car;
	}


	@Override
	public void move() {
		
		long startime=System.currentTimeMillis();
		System.out.println("汽车开始行驶");
		car.move();
		long endtime=System.currentTimeMillis();
		System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");
	}

}

LogProxy记录日志代理类

public class LogProxy implements Moveable {
	
	private Moveable car;
	
	public LogProxy(Moveable car) {
		super();
		this.car = car;
	}

	@Override
	public void move() {
		System.out.println("开始记录日志");
		car.move();
		System.out.println("日志记录结束");
	}

}

测试类

public class Client {

	public static void main(String[] args) {
		//使用聚合的方式实现的静态代理
		Car car=new Car();
		Moveable mt=new LogProxy(car);
		Moveable m=new TimeProxy(mt);	
		m.move();
	}

}
运行结果




JDK动态代理:只能代理实现了接口的类。

TimeHandler类(实现InvocationHandler接口)

public class TimeHandler implements InvocationHandler {

	private Object target;
	
	public TimeHandler(Object target) {
		this.target=target;
	}

	/*
	 * 参数:
	 * proxy被代理对象
	 * method被代理对象的方法
	 * args方法的参数
	 * 
	 * 返回值:
	 * Object  方法的返回值
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		long startime=System.currentTimeMillis();
		System.out.println("汽车开始行驶");
		
		method.invoke(target);
		
		long endtime=System.currentTimeMillis();
		System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");
		
		return null;
	}

}

测试类

public class Test {
	//JDK动态代理测试类
	public static void main(String[] args) {
		Car car=new Car();
		InvocationHandler h=new TimeHandler(car);
		Class<?> cls=car.getClass();
		
		/*
		 * loader:类加载器
		 * interfaces:被代理类实现的接口
		 * h:InvocationHandler对象(事务处理器)
		 */
		Moveable m=(Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h); //生成代理对象
		
		m.move();
	}

}





CGLIB动态代理:1.针对类来实现代理  2.对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。

首先你需要引入cglib-nodep-2.2.jar包

被代理类

public class Plane {
	
	public void move(){
		System.out.println("飞机飞行中......");
	}
	
}


CglibProxy类

public class CglibProxy implements MethodInterceptor {

	
	private Enhancer enhancer=new Enhancer();
	
	//返回代理类对象
	public Object getProxy(Class<?> cls){
		//为cls创建子类代理类
		enhancer.setSuperclass(cls);		
		enhancer.setCallback(this);
		
		return enhancer.create();

	}
	/*
	 * 拦截所有目标类方法的调用
	 * 参数:
	 * obj   目标类的实例
	 * m     目标方法的反射对象
	 * args  方法的参数
	 * proxy 代理类的实例
	 */
	@Override
	public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {
		
		System.out.println("日志开始..");
		//代理类调用父类的方法
		proxy.invokeSuper(obj, args);
		System.out.println("日志结束...");
		return null;
	}

}


测试类

public class Client {

	public static void main(String[] args) {
		CglibProxy proxy=new CglibProxy();
		
		Plane p=(Plane) proxy.getProxy(Plane.class);

		p.move();
	}

}





JDK动态代理实现原理:

实现功能:通过Proxy的newProxyInstance方法返回代理对象
步骤:1.声明一段源码(动态产生代理)    2.编译源码(JDK Compiler API),产生新的类(代理类)     3.将此类load到内存中,产生一个新的对象(代理对象)    4.return代理对象
下面的代码是我在之前静态代理的基础上修改的。

Car类

public class Car implements Moveable {
	@Override
	public void move() {
		
		try {
			Thread.sleep(new Random().nextInt(1000));
			System.out.println("汽车行驶中.....");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

接口

public interface Moveable {
	void move();
}

自定义的InvocationHandler接口

public interface InvocationHandler {
	
	public void invoke(Object obj,Method m);
}
因为move方法没有参数,这里invoke的参数也就没加上"方法的参数"

TimeHandler类

public class TimeHandler implements InvocationHandler {

	
	private Object target;
	
	
	public TimeHandler(Object target) {
		super();
		this.target = target;
	}


	@Override
	public void invoke(Object obj, Method m) {
		try {
			long startime=System.currentTimeMillis();
			System.out.println("汽车开始行驶");
			
			m.invoke(target);
			
			long endtime=System.currentTimeMillis();
			System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}


最重要的Proxy类

public class Proxy {
	
	//infce为接口的Class对象
	public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{
		
		String rt="\r\n";     //windows换行符
		
		String methodStr="";
		for(Method m:infce.getMethods()){
			methodStr+=
			"    @Override"+rt+
			"	public void "+m.getName()+"() {"+rt+
			"      try{"+rt+
			"		 Method md="+infce.getName()+".class.getMethod(\""+m.getName()+"\");"+rt+
		    "        h.invoke(this,md);"+rt+
		    "      }catch(Exception e){e.printStackTrace();}"+rt+
			"	}";
		}
		
				
		//1.声明一段源码
		String str=
		"package com.wulijian.staticproxy;"+rt+
		"import com.wulijian.staticproxy.InvocationHandler;"+rt+
		"import java.lang.reflect.Method;"+rt+
		
		"public class $Proxy0 implements "+infce.getName()+"{"+rt+     //jdk生成的动态代理类名字是$Proxy0

		"    private InvocationHandler h;"+rt+	
		
		"	 public $Proxy0(InvocationHandler h) {"+rt+
		"        this.h = h;"+rt+
		"    }"+rt+
		
		methodStr+rt+

		"}";
		
		
		//2.编译源码,产生代理类
		//String filename=System.getProperty("user.dir");   当前工程所在路径(F:\eclipse_workspace\Proxy)
		String filename=System.getProperty("user.dir")+"/bin/com/wulijian/staticproxy/$Proxy0.java";
		
	    File file=new File(filename);
	    
	    FileUtils.writeStringToFile(file, str);
		
	    //得到编译器
	    JavaCompiler compiler=ToolProvider.getSystemJavaCompiler();
	    //创建文件管理者
	    StandardJavaFileManager fileMgr=compiler.getStandardFileManager(null, null, null);
	    //获取文件
	    Iterable units=fileMgr.getJavaFileObjects(filename);
	    
	    //编译任务
	    CompilationTask t=compiler.getTask(null, fileMgr, null, null, null, units);
	    
	    //进行编译,生成.class文件
	    t.call();
	    
	    fileMgr.close();
	    
	    
	    //3.将class文件load到内存中
	    ClassLoader cl=ClassLoader.getSystemClassLoader();
	    Class c=cl.loadClass("com.wulijian.staticproxy.$Proxy0");
	    
	    Constructor ctr=c.getConstructor(InvocationHandler.class);
	    //得到反射类实例
	    return ctr.newInstance(h);
	}
}


测试类

public class Client {

	public static void main(String[] args) throws Exception {
		
		Car car=new Car();
		InvocationHandler h=new TimeHandler(car);
		Moveable m=(Moveable) Proxy.newProxyInstance(Moveable.class,h);
		
		m.move();
	}

}

结果如图




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值