动态代理

Java反射包(java.lang.reflect)给编程带来了很多的灵活性,代理能够维持类的原貌,很好地解决java灵活性较差的问题。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。 

 

静态代理:

 

抽象接口:

package DesignPattern.staticProxy;


public interface Hello {
	

	public abstract void say();
	
}


 

实现类:

package DesignPattern.staticProxy;


public class HelloImpl  implements Hello{

//	@Override
	public void say() {
		// TODO Auto-generated method stub
		System.out.println("lcx hello");
	}
	
}


代理类:

package DesignPattern.staticProxy;


public class HelloProxy implements Hello{

	private Hello hi;

	
	/**
	 * @param hi
	 */
	public HelloProxy(Hello hi) {
		super();
		this.hi = hi;
	}


	public void say() {
		// TODO Auto-generated method stub
		doBefore();
		hi.say();
		doAfter();
	}
	
	private void doBefore(){
		System.out.println("before method invoke");
	}

	private void doAfter(){
		System.out.println("after method invoke");
	}
}


测试类:

package DesignPattern.staticProxy;


public class HelloTest {

	public static void main(String[] args) {
		Hello hw=new HelloImpl();
		HelloProxy proxy=new HelloProxy(hw);
		proxy.say();
	}
}


 

结果如下:

before method invoke
lcx hello
after method invoke

 

通过上述4个类,对HelloImpl类实现了改造,完成了对say()方法的包装处理。

 

动态代理

 

接口类:

package DesignPattern.dynamicProxy;


public interface Hello {
	
	public abstract void say();
	
}


实现类:

package DesignPattern.dynamicProxy;


public class HelloImpl  implements Hello{

//	@Override
	public void say() {
		// TODO Auto-generated method stub
		System.out.println("lcx hello");
	}

}


代理类:

package DesignPattern.dynamicProxy;

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


public class HelloHandler implements InvocationHandler {

	private Object obj;


	/**
	 * @param obj
	 */
	public HelloHandler(Object obj) {
		super();
		this.obj = obj;
	}


	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub

		doBefore();
		Object res=method.invoke(obj, args);
		doAfter();
		return res;
	}

	private void doBefore(){
		System.out.println("before method invoke");
	}

	private void doAfter(){
		System.out.println("after method invoke");
	}

}


测试类:

package DesignPattern.dynamicProxy;

import java.lang.reflect.Proxy;


public class HelloTest {

	public static void main(String[] args) {
		Hello hw=new HelloImpl();
		HelloHandler handler=new HelloHandler(hw);
		Hello proxy=(Hello) Proxy.newProxyInstance(hw.getClass().getClassLoader(), hw.getClass().getInterfaces(), handler);
		proxy.say();
	}
}


最后打印结果

before method invoke
lcx hello
after method invoke

Proxy源码研究

Proxy中主要方法是newProxyInstance方法,代码如下:

 /**
     * Returns an instance of a proxy class for the specified interfaces
     * that dispatches method invocations to the specified invocation
     * handler.  This method is equivalent to:
     * 
     *     Proxy.getProxyClass(loader, interfaces).
     *         getConstructor(new Class[] { InvocationHandler.class }).
     *         newInstance(new Object[] { handler });
     * 
* *

Proxy.newProxyInstance throws * IllegalArgumentException for the same reasons that * Proxy.getProxyClass does. * * @param loader the class loader to define the proxy class * @param interfaces the list of interfaces for the proxy class * to implement * @param h the invocation handler to dispatch method invocations to * @return a proxy instance with the specified invocation handler of a * proxy class that is defined by the specified class loader * and that implements the specified interfaces * @throws IllegalArgumentException if any of the restrictions on the * parameters that may be passed to getProxyClass * are violated * @throws NullPointerException if the interfaces array * argument or any of its elements are null, or * if the invocation handler, h, is * null */ public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) throws IllegalArgumentException { if (h == null) { throw new NullPointerException(); } /* * Look up or generate the designated proxy class. */ Class cl = getProxyClass(loader, interfaces); /* * Invoke its constructor with the designated invocation handler. */ 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()); } }

注释中:Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocationhandler.

大致意思是:返回一个指定接口与方法处理者的代理类对象,实际上就是反射。

Class cl = getProxyClass(loader, interfaces)实现了获取Proxy类对应的对象。

cons.newInstance(new Object[] { h })实现了通过相关的类得到Proxy对象。

总结,静态代理与动态代理区别:

1. 静态代理原理是组合,动态代理原理是反射。

2. 静态代理灵活性仍然较差,只能对一个方法进行代理。而动态代理可以对多方法进行处理。

3. 在代码维护过程中,如果对类方法名称等进行修改(如将方法名修改为say1()),或者增减方法,动态代理的代理类无需修改任何代码,静态代理则不然。我们可以看到HelloHandler代码中,没有包含任何与Hello相关的东西,所以内容完全有obj传入。

总之,动态代理的好处全部源于反射机制。 

 

 

 

你可能感兴趣的:(设计模式探究,设计模式,面向对象,反射)