《Java与模式》之 代理模式(jdk动态代理)

《Java与模式》一书中这样介绍代理模式的:


《Java与模式》之 代理模式(jdk动态代理)_第1张图片

JDK动态代理的核心:

Proxy – 用于创建给定接口的子类,在内存中动态的创建。$Proxy0. - 此类只使用一次。

 InovocationHandler– 执行句柄。在执行时可以获取被代理类的所有反射。 - 用户的每一次调用都会被这个句柄拦截到。

JDK动态代理的作用:

  在内存中创建某个接口的子类。

  拦截所有在代理上执行的方法。( 除了getClass方法。)


代码结构如下:



package Interview;

public interface IInteviewer {
	//面试者面试
	String Interview(String name);
}


package Interview;

public class Inteviewer implements IInteviewer{

	@Override
	public String Interview(String name) {
		System.out.println("您好,我是今天的面试者 "+ name);
		return name;
	}

}

package Interview;

import java.lang.reflect.Proxy;

public class ProxyDemo {
	public static void main(String[] args) {
		final IInteviewer obj = new Inteviewer();
		Object proxyedObj = 
				Proxy.newProxyInstance(
						ProxyDemo.class.getClassLoader(), //类加载器
						new Class[]{IInteviewer.class}, //被代理类的接口数组
						new InterviewProxy(obj));
		
		IInteviewer obj2 = (IInteviewer) proxyedObj;
		obj2.Interview("阿呆");
	}
}

package Interview;

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

public class InterviewProxy implements InvocationHandler {
	
	private Object obj ;

	public InterviewProxy(Object obj) {
		this.obj = obj;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object invoke = method.invoke(obj, args);
		return invoke;
	}

}

运行结果如下:

《Java与模式》之 代理模式(jdk动态代理)_第2张图片


当然这个只是简单的得到了代理对象,并调用代理对象的方法。貌似代理对象没有起到多大的作用,下面我们就用代理模拟spring的事务(简单演示)。



package com.demo.se.proxy;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(value=ElementType.METHOD)
public @interface Tx {

}


package com.demo.se.proxy;
public interface IOne {
	@Tx
	void save();//添加需要处理事务的注解
	Object query(String id);
}

package com.demo.se.proxy;
public class One implements IOne {
	public void save() {
		System.err.println("保存。。。");
	}
	public Object query(String id) {
		System.err.println("根据ID查询。。。。id=" + id);
		return id;
	}
}

package com.demo.se.proxy;

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

public class TxProxy implements InvocationHandler {
	
	private Object obj;
	  
	public TxProxy(Object obj) {
		super();
		this.obj = obj;
	}

	//接收一个被代理的对象
	public static Object newProxy(Object o){
		Object proxy = Proxy.newProxyInstance(
					TxProxy.class.getClassLoader(), 
					o.getClass().getInterfaces(), 
					new TxProxy(o));
		return proxy;
	}
	
	//使用泛型,接收被代理的Class对象
	public static T newProxy(Class cls){
		Object o = null;
		try {
			o = cls.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		Object proxy = Proxy.newProxyInstance(TxProxy.class.getClassLoader(), 
				  o.getClass().getInterfaces(), 
				  new TxProxy(o));
		return (T)proxy;

	}


	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object res = null;
		if(method.isAnnotationPresent(Tx.class)){//判断是否添加了Tx事务注解
			try{
				System.err.println("开始拦截..从当前线程局部对象中获取一个连接");
				res = method.invoke(this.obj, args);
				System.err.println("拦截完成提交");
			}catch(Exception e){
				System.err.println("回滚");
				throw new RuntimeException(e.getMessage(),e);
			}finally{
				System.err.println("结束。。。放回连接池");
			}
		}else{
			res = method.invoke(this.obj, args);
		}
		return res;

	}

}

package com.demo.se.proxy;

import org.junit.Test;

public class TxTest {
	@Test
	public void t1(){
	IOne one = TxProxy.newProxy(One.class);
	one.save();  //此方法将会处理事务
	one.query("001");
	}

}

运行结果:

《Java与模式》之 代理模式(jdk动态代理)_第3张图片


通过以上代码相信你对代理应该有了一个认识,下篇介绍cglib代理以及简单的mybatis中使用代理的。

你可能感兴趣的:(设计模式)