Java代理模式之动态代理

昨天说到了静态代理,静态代理是在事先知道真实对象的情况下产生的代理类,一个代理对象对应一个真实对象(代理对象持有对真实对象的引用),如果有很多真实对象需要进行代理,我们就要产生出很多代理对象,这样,会形成代理对象冗余;或者我们根本不知道代理对象是什么,那这样又要如何处理呢?

前面说过反射可以在运行时确定一个类的类型信息,所以我们可以通过反射来动态代理对象,JDK已经提供了相应的API,下面就可以通过API来实现动态代理.

JDK动态代理的API存放在java.lang.reflect包下,主要涉及到:

(1)InvocationHandler接口

 

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
	throws Throwable;
}

 该接口只有一个invoke方法,此方法用来处理代理对象上的方法调用,即代理对象上相关方法的调用会通过此方法来对真实对象

目标方法的调用

(2)Proxy类

 public static Object newProxyInstance(ClassLoader loader,
					  Class<?>[] interfaces,
					  InvocationHandler h)
	throws IllegalArgumentException
    {
	if (h == null) {
	    throw new NullPointerException();
	}

	//通过类加载器得到代理类的Class对象
	Class cl = getProxyClass(loader, interfaces);

	
	try { 
            //得到代理对象的构造方法
	    Constructor cons = cl.getConstructor(constructorParams);
	    //返回该代理对象
            return (Object) cons.newInstance(new Object[] { h });
	} catch (NoSuchMethodException e) {
	    throw new InternalError(e.toString());
	} catch (IllegalAccessException e) {
	    throw new InternalError(e.toString());
	} catch (InstantiationException e) {
	    throw new InternalError(e.toString());
	} catch (InvocationTargetException e) {
	    throw new InternalError(e.toString());
	}
    }

 该方法为Proxy的最主要方法,用于动态产生我们需要的代理对象,而不必再像静态代理那样需要事先知道真实对象.

到底什么是动态代理?

在动态代理中,代理会在运行时根据你传入的一组接口动态生成,默认生成的代理类可以作为该组接口中任何一个实现类来使用,这个类仅仅是一个代理类,它不会完成真正的代理操作,所以在该类生成时会传入一个实现了InvocationHandler接口的实现类,他会完成真正的代理操作,即相关方法的调用;下面看一个实例:

public interface Subject {

	public void doSth();
}
 public class RealSubject implements Subject {
	@Override
	public void doSth() {
		System.out.println("RealSubject-->doSth");
	}
}

 

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

 

public class Client {
	public static void main(String[] args) {
		RealSubject rs = new RealSubject();
		
		InvocationHandler dynamic = new DynamicProxySubject(rs);
		
		Subject subject = (Subject)Proxy.newProxyInstance(dynamic.getClass().getClassLoader(),rs.getClass().getInterfaces(),dynamic);
		subject.doSth();//当执行这个方法调用时其实是执行的invocationhandler接口实现类的invoke方法
	}
}

 这就是动态代理实现的helloword代码,后面的struts2、spring中用到了很多动态代理模式,学好动态代理对理解这些框架的原理非常有用

 

你可能感兴趣的:(java,spring,jdk,框架)