代理模式(Java实现)

what? why?

代理对象控制对真实对象的访问,so,为什么需要进行访问控制?

How:

代理模式有3种角色:

  • 抽象角色:声明真实对象和代理对象之间的共同接口,用来规范代理对象的行为;
  • 代理角色:内部含有对真实对象的引用;提供和真实对象一致的接口以便在任何时候都能代替真实对象;可以在执行真实对象的操作时附加操作。
  • 真实角色:真实对象,被代理。

静态代理

静态代理是指代理角色在运行之前已经存在,即运行前需要编码编译

//客户端
public class Client
{
	public static void main(String[] args)
	{
		Subject subject = new ProxySubject();

		subject.request();
	}
}

//抽象角色,代理角色和真实角色都实现或继承他
public abstract class Subject
{
	public abstract void request();
}

//代理角色
public class ProxySubject extends Subject
{
	private RealSubject realSubject; //真实角色的引用

	public void request()
	{
	    //附加功能
		this.preRequest();

		if(null == realSubject)
		{
			realSubject = new RealSubject();
		}

		realSubject.request();

		this.postRequest();
	}

	private void preRequest()
	{
		System.out.println("pre request");
	}

	private void postRequest()
	{
		System.out.println("post request");
	}
}

//真实角色
public class RealSubject extends Subject
{
	public void request()
	{
		System.out.println("From real subject.");
	}
}

why动态代理?

  • 就静态代理而言: 一个真实角色必须对应一个代理角色,大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这些问题可以通过动态代理来解决,所谓动态代理是指代理角色在运行时动态生成的技术。
  • 采用动态代理,一个InvocationHandler接口的实例可以代理不同的对象,也就是说相同的代理逻辑只用写一次代码

java动态代理框架

  • java.lang.reflect.InvocationHandlerjava.lang.reflect.Proxy组成,InvocationHandler接口实例Proxy.newProxyInstance生成的对象实例进行不同分工,一起充当了代理角色。
  • InvocationHandler实例只有一个invoke方法,负责调用真实对象的方法
  • Proxy会将真实对象注入到InvocationHandler实例;Proxy在运行时动态生成和真实对象具有相同接口的代理对象,然后调用InvocationHandler实例invoke`方法;
  • Proxy运行时生成代理类的字节码的动作由sun.misc.ProxyGenerator.generateProxyClass()完成
一个实例
public class Client
{
	public static void main(String[] args)
	{
		RealSubject realSubject = new RealSubject();

		InvocationHandler handler = new DynamicSubject(realSubject);

		Class<?> classType = handler.getClass();


		Subject subject = (Subject) Proxy.newProxyInstance(classType
				.getClassLoader(), realSubject.getClass().getInterfaces(),
				handler);

		subject.request();

		System.out.println(subject.getClass());

	}
}

public class DynamicSubject implements InvocationHandler
{
	private Object sub;

	public DynamicSubject(Object obj)
	{
		this.sub = obj;
	}

	//正是由于这里采用了反射,所以才避免了静态代理和真实对象绑定的//问题。
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable
	{
		System.out.println("before calling: " + method);

		method.invoke(sub, args);

		System.out.println(args == null);

		System.out.println("after calling: " + method);

		return null;
	}

}

public class RealSubject implements Subject
{
	public void request()
	{
		System.out.println("From real subject!");
	}

}

//一致性接口,真实对象和动态生成的代理对象都要实现。
public interface Subject
{
	public void request();
}
另一个例子: 代理List
public class Client<T> implements InvocationHandler{
	T obj;
	public Client(T obj){
		this.obj = obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("Proxy!");

		return method.invoke(obj,args);
	}

	public static void main(String[] args) {
		List<Integer> list = new LinkedList<>();
		Client<List<Integer>> handler = new Client<>(list);

		//pro为动态生成的代理对象
		@SuppressWarnings("unchecked")
		List<Integer> pro = (List<Integer>)Proxy.newProxyInstance(Handler.class.getClassLoader(),
				list.getClass().getInterfaces(),handler);

		//通过代理pro调用add方法。pro会让handler通过调用invoke调用add方法
		for(int i=0;i<10;i++)
			pro.add(i);

		for(Iterator<Integer> it =pro.iterator();it.hasNext();System.out.print(it.next()));

	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值