写一点代理模式的个人理解
代理模式可以说是:本来由A去执行的方法,但是A不去执行,由B去代A执行。
代理可分为静态代理和动态代理,静态代理中用代理类也实现了接口的方法。动态代理中用到了反射。
先看一下静态代理的草图:
Real和代理类Proxy同时实现了接口,在客户端调用时直接调用代理类即可,然后代理类中的Real对象再去调用真正实现的方法,这样便形成了代理,达到了使用代理的目的。
优点是:代理类将真实类的方法封装了起来,可以在调用真正实现方法时添加前置和后置方法。
缺点是:实现一个代理类会多出很多的代码,造成了冗余,而且这个代理类必须事先存在。
不写这个代码了。
动态代理实现,先贴代码:
package Proxy;
import java.lang.reflect.*;
interface BusinessFoo{
void foo();
}
interface BusinessBar{
String bar(String message);
}
class BusinessFooImpl implements BusinessFoo{
@Override
public void foo() {
// TODO Auto-generated method stub
System.out.println("BusinessFooImpl.foo()");
}
}
class BusinessBaeImpl implements BusinessBar{
@Override
public String bar(String message) {
// TODO Auto-generated method stub
System.out.println("BusinessBarImpl.bar()");
return message;
}
}
class BusinessImplProxy implements InvocationHandler{
private Object obj; //obj是真正实现方法的对象
BusinessImplProxy(){
}
BusinessImplProxy(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object result = null;
doBefore();
result = method.invoke(obj, args); //去调用真正的方法 foo()和bar()
doAfter();
return result;
}
public void doBefore() {
System.out.println("Do something before Business logic");
}
public void doAfter() {
System.out.println("Do something after Business logic");
}
public static Object factory(Object obj){
Class<?> cls = obj.getClass();
System.out.println("cls.getClass is:"+cls.getClass());
System.out.println("obj的类型是:"+obj.getClass().getName());
Class<?>[] interfaces = cls.getInterfaces();
for(Class<?> itf : interfaces)
{
System.out.println(itf.getName());
}
System.out.println("ClassLoader is: "+cls.getClassLoader()); //ClassLoader is: sun.misc.Launcher$AppClassLoader@1372a1a
return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),
new BusinessImplProxy(obj)); //返回一个代理对象 getClassLoader()表示该运行时类 //的加载,getInterfaces()是得到运行时类的实现接口,动态代理只是实现了接口,没有实现抽象类,new BusinessImplProxy(obj)则表示真正对///象
}
}
public class DymnaticProxy {
public static void main(String[] args) {
// TODO Auto-generated method stub
BusinessFooImpl bFooImpl = new BusinessFooImpl();
BusinessFoo bf = (BusinessFoo)BusinessImplProxy.factory(bFooImpl);
bf.foo(); //去调用invoke();这一块调用哪个真正的方法,invoke中则去调用哪个
System.out.println();
BusinessBaeImpl bbar = new BusinessBaeImpl();
BusinessBar bb = (BusinessBar)BusinessImplProxy.factory(bbar);
String messageString = bb.bar("Hello world"); //去调用invoke();
System.out.println(messageString);
}
}
代理类必须得实现InvocationHandle的接口,该接口中有一个invoke方法。
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法由程序员来指定参数动态返回需要的代理类,而invoke(Object proxy,Method method, Object[] args) 方法则是由JVM在运行时动态调用的。当执行“bb.bar("Hello,World");”方法时,JVM动态指派“调用处理器”,向外层invoke传递参数,并调用method.invoke(obj,args)真正执行!
BusinessImplProxy.Factory静态方法用来动态生成代理类(“代理角色”),在运行时根据不同的业务逻辑接口BusinessFoo和BusinessBar,在运行时分别动态生成了代理角色。“抽象角色”、“代理角色”以及调用处理器(实现InvocationHandler接口的类)这三者都可以改变,所以说JAVA的动态代理十分强大。
在动态代理使用过程中有几个重要的类:Proxy,Method,Class<?>. 还有这个InvocationHandler接口。
Proxy类只能从子类为InvocationHandler构造一个Proxy实例,Proxy类的无参构造函数为私有,禁止实例化。
/**
* the invocation handler for this proxy instance.
* @serial
*/
protected InvocationHandler h;
/**
* Prohibits instantiation.
*/
private Proxy() {
}
/**
* Constructs a new <code>Proxy</code> instance from a subclass
* (typically, a dynamic proxy class) with the specified value
* for its invocation handler.
*
* @param h the invocation handler for this proxy instance
*/
protected Proxy(InvocationHandler h) {
this.h = h;
}
<span style="font-size:14px;">
</span>
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
throws IllegalArgumentException
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());
}
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
该方法有三个参数:第三个参数是一个Object类型的数组,它传递的是foo()的参数,第二个参数是Method类的对象,这个类要关注一下。
ublic Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
先写这些