首页 > 技术文章 > java中的静态代理和动态代理,入门整理

jinlin 2016-08-27 21:05 原文

静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

静态代理在感觉上和装饰设计模式很像

  1)、在代理类中实现被代理类实现的所有接口,这样保证了被代理类所能实现的方法,代理类也能实现,保证了两边行为的一致性,代理类就能转型为被代理类,当作被代理类处理。而代理中有被代理类的对象,这样,在代理类的内部实现接口方法时就能调用被代理类的方法,从而进行对被代理类的封装。

简单的示范:

package cn.edu.cjl;

public interface Subject {
	public void replace();
}

  

package cn.edu.cjl;

public class RealSubject implements Subject{

	@Override
	public void replace() {
		// TODO Auto-generated method stub
		System.out.println("real subject...");
	}

}

  

package cn.edu.cjl;

public class daili implements Subject {
	RealSubject subject;
	@Override
	public void replace() {
		System.out.println("before...");
		if(subject==null){
			subject=new RealSubject();
		}
		subject.replace();
		System.out.println("after...");
	}

}

  

package cn.edu.cjl;

public class Client {
	public static void main(String[] args) {
		Subject subject=new daili();
		subject.replace();
	}
}

 代码中定义接口Subject,真实的实现类是RealSubject,但是在在主方法中调用的是daili类,在daili类中同样实现了Subject接口,但是真实上调用的是RealSubject类的方法。这就是静态代理。

  静态代理可以解决直接访问类方法带来的问题,但是本身也有问题,就是当大量的使用静态代理时类的个数将双倍的增加,不利于程序的管理。

 

 

动态代理使用了反射技术,一个代理类可以为任意类提供代理。

  代理类必须实现InvocationHandler接口,对代理实例调用方法时,将对方法调用进行编码并将其指派到它的代理程序的 invoke 方法。

  invoke方法运用反射技术,通过java.lang.reflect.Proxy类中提供的静态方法 newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序,也就是代理类实现的InvocationHandler接口中的invoke方法中,这个方法的各个参数的意思是

ClassLoader loader:类加载器,定义代理类的类加载器,可以任意指定。

Class<?>[] interfaces: 被代理类所实现的所有接口的class数组,可以用class对象的getInterfaces()方法得到。

InvocationHandler h:实现了InvocationHandler接口的对象。

简单的事例:

package cn.edu.cjl.proxy;

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

public class proxy implements InvocationHandler {
	private Object object;
	public proxy(Object obj){
		this.object=obj;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("before");
		Object resultObject= method.invoke(object, args);
		System.out.println("after");
		return resultObject;
	}

}

  

package cn.edu.cjl.proxy;

import java.lang.reflect.Proxy;

public class Client {
	public static void main(String[] args) {
		Subject subject = null;
		RealSubject rSubject = new RealSubject();
		proxy proxy = new proxy(rSubject);
		subject = (Subject) Proxy.newProxyInstance(Client.class
				.getClassLoader(), rSubject.getClass().getInterfaces(), proxy);
		subject.replace();
	}
}

  

 

推荐阅读