Java反射与代理模式

为什么要使用代理模式?

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

例如:我要买一个电脑,但是我不能没有任何准备工作就去买电脑,比如买点脑之前,必须先准备好钱,找到去商店的地址,然后付钱买电脑,买了电脑之后还应该把电脑拿回家开机。

其中除了买电脑这个核心业务由主类完成,其他的买电脑前和买电脑后的一些操作全部由辅助类来完成。这就是代理设计模式。


代理模式的优点:

(1). 职责清晰

        真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务。

(2). 代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。

(3). 高扩展性。

代理模式的分类:

静态代理:N个接口对应N个真实业务类和N个辅助实现类。

动态代理:N个接口对应N个真实业务类和1个辅助实现类。

一个静态的代理模式应该有以下几部分组成:

一个接口:IObject

一个真实业务类:RealObject

一个辅助实现类:ProxyObject


一个静态代理模式的例子:

接口定义:

public interface IMessage {
	void msg();
}

真实业务类:

public class RealMessage implements IMessage{
	@Override
	public void msg() {
		System.out.println("发送消息");
	}
}

辅助类:

public class ProxyMessage implements IMessage{
	private IMessage realMsg;
	public ProxyMessage(IMessage realMsg) {
		this.realMsg = realMsg;
	}
	
	@Override
	public void msg() {
		this.beforeMsg();
		this.realMsg.msg();
		this.afterMsg();
	}
	
	public void beforeMsg() {
		System.out.println("联网");
	}
	
	public void afterMsg() {
		System.out.println("断开连接");
	}
}

测试:

public class Test {
	public static void main(String[] args) throws Exception {
		IMessage proxyMessage = new ProxyMessage(new RealMessage());
		proxyMessage.msg();
	}
}

运行结果:

普通代理模式与通用工厂模式

工厂模式好处:

客户端不需要改动代码,只需要改变传入的参数。将客户端与服务端解耦。

以上其他代码不变,新增Factory类:

import java.lang.reflect.Constructor;
/**
 * 代理模式与工厂模式
 */
public class Factory {
	private Factory() {}
	
	/**
	 * 返回一个代理类的对象
	 * @param proxyClassName 
	 * @param realClassName
	 * @return
	 * @throws Exception
	 */
	public static <T> T getInstance(String proxyClassName, String realClassName) throws Exception {
		// 获取辅助类的Class对象
		Class<?> proxyCls = Class.forName(proxyClassName);
		// 获取真实业务类的Class对象
		Class<?> realCls = Class.forName(realClassName);
		// 获取真实业务类对象
		T realObj = (T)realCls.newInstance();
		// 获取辅助类对象
		Constructor proxyConstructor = proxyCls.getConstructor(realCls.getInterfaces()[0]);
		T t = (T) proxyConstructor.newInstance(realObj);
		return t;
	}
}

测试类:

public class Test {
	public static void main(String[] args) throws Exception {
		IMessage msg = Factory.getInstance("静态代理通用工厂.ProxyMessage", "静态代理通用工厂.RealMessage");
		msg.msg();
	}
}

运行结果:

静态代理的缺点:所有的代理类的代码结构类似,所以代码的冗余度过高。动态代理模式很好的解决了这一缺点

动态代理模式:

当有多个以上代理模式时,由于所有的代理类的结构都是一样的,可以使用一个辅助类来代替所有的辅助类

实现以上需求需要代理类实现InvocationHandler接口

结构如下:


Factory类:用于生产代理类对象和真实业务类对象

ISubject:业务实现接口

Person类:真实业务实现类

ProxyObject类:通用的代理类

Test类:测试类


代理类的代码如下:

class ProxyObject implements InvocationHandler{
	private Object realObject;
	
	/**
	 * 用于将真实业务类和代理类绑定
	 * @param realObject
	 * @return
	 */
	public Object bind(Object realObject) {
		this.realObject = realObject;
		return Proxy.newProxyInstance(realObject.getClass().getClassLoader(), 
				realObject.getClass().getInterfaces(), this);
	}

	/**
	 * 两个通用的辅助真实处理业务逻辑的方法。
	 */
	public void beforeHandle() {
		System.out.println("准备处理业务");
	}
	
	public void afterHandle() {
		System.out.println("善后工作");
	}
	
	/**
	 * 这个方法是自动调用的,当绑定之后调用真实业务逻辑的时候,将会自动调用\
	 * proxy 在其上调用该方法的代理实例
	 * method 与代理实例上调用的接口方法相对应的方法实例(真实处理业务的方法)
	 * args method方法传入的参数。
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		beforeHandle();
		Object ret = method.invoke(realObject, args);
		afterHandle();
		return ret;
	}
}

工厂类代码如下:

import java.lang.reflect.Method;

/**
 * 工厂
 */
public class Factory {
	private Factory() {}
	
	/**
	 * 获取realObject的实例
	 * @param proxyName 代理类类名称
	 * @param realName 真实类的名称
	 * @return
	 * @throws Exception 
	 */
	public static Object  getInstance(String proxyClassName, String realClassName) throws Exception {
		//获取代理类
		Class<?> proxyClass = Class.forName(proxyClassName);
		
		//获取真实业务类
		Class<?> realClass = Class.forName(realClassName);
		
		// 获取代理类bind方法
		Method bindMethod = proxyClass.getDeclaredMethod("bind", Object.class);
		// 返回代理类对象
		return bindMethod.invoke(proxyClass.newInstance(), realClass.newInstance());
	}
}

测试类:

public class Test {
	public static void main(String[] args) throws Exception {
		ISubject subject =(ISubject) Factory.getInstance("动态代理.ProxyObject", "动态代理.Person");
		subject.eat();
	}
}

运行结果:




猜你喜欢

转载自blog.csdn.net/bugggget/article/details/80280980