设计模式之代理模式
2019-05-03 本文已影响0人
古月沧澜
动态代理
含义:
动态代理是个通用框架,主要处理审计的问题,就是面向切面编程,在不改变代码结构的基础上,增加和控制对象的行为。
类图:
通用类:
1.抽象主题:动态代理只能代理接口,必须有实现类.
/**抽象主题
* Created by Administrator on 2019/5/2.
*/
public interface Subject {
void doSomething();
}
2.具体主题
/**真实主题
* Created by Administrator on 2019/5/2.
*/
public class RealSubject implements Subject {
@Override
public void doSomething() {
}
}
3.请求处理器
/**请求处理器
* Created by Administrator on 2019/5/2.
*/
public class MynvocationHandler implements InvocationHandler {
private Object obj;
public MynvocationHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(obj, args);
return result;
}
}
4.动态代理类
/**动态代理
* Created by Administrator on 2019/5/2.
*/
public class DynamicProxy<T> {
/**<T> 用来申明这是一个泛型方法,跟编译器说T是一个泛型占位符,我存什么类型,他就是什么类型,而不是其他的东西,比如类名,T可能是别的类的类名。
* */
public static <T> T newInstance(ClassLoader classLoader,Class<?>[] interfaces ,
InvocationHandler invocationHandler){
if(true){
IAdvice advice=new Advice();
advice.advice();
}
return (T)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
/**
* Created by Administrator on 2019/5/3.
*/
public class SubjectDynamicProxy extends DynamicProxy {
/**<T> ,只是泛型声明,用来申明这是一个泛型方法,跟编译器说T是一个泛型占位符,我存什么类型,他就是什么类型,而不是其他的东西,比如类名,T可能是别的类的类名。
* */
public static <T> T newInstance(Subject subject){
ClassLoader classLoader = subject.getClass().getClassLoader();
Class<?>[] interfaces = subject.getClass().getInterfaces();
InvocationHandler invocationHandler=new MynvocationHandler(subject);
return (T) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
5.通知接口
/**通知接口,织入进来
* Created by Administrator on 2019/5/2.
*/
public interface IAdvice {
void advice();
}
6.具体通知
/**通知实现接口
* Created by Administrator on 2019/5/2.
*/
public class Advice implements IAdvice {
@Override
public void advice() {
System.out.println("前置通知");
}
}
相关资料整理
1.相关类
一.相关类及其方法:
java.lang.reflect.Proxy,
Proxy 提供用于创建动态代理类和实例的静态方法.
newProxyInstance()
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
(详见api文档)
java.lang.reflect.InvocationHandler,
InvocationHandler 是代理实例的调用处理程序 实现的接口。
invoke()
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
(详见api文档)
2.Proxy源码:
1. public static Object newProxyInstance(ClassLoader loader,
2. Class<?>[] interfaces,
3. InvocationHandler h)
4. throws IllegalArgumentException
5. {
6. if (h == null) {
7. throw new NullPointerException();
8. }
10. /*
11. * Look up or generate the designated proxy class.
12. */
13. Class cl = getProxyClass(loader, interfaces);
15. /*
16. * Invoke its constructor with the designated invocation handler.
17. */
18. try {
19. /*
20. * Proxy源码开始有这样的定义:
21. * private final static Class[] constructorParams = { InvocationHandler.class };
22. * cons即是形参为InvocationHandler类型的构造方法
23. */
24. Constructor cons = cl.getConstructor(constructorParams);
25. return (Object) cons.newInstance(new Object[] { h });
26. } catch (NoSuchMethodException e) {
27. throw new InternalError(e.toString());
28. } catch (IllegalAccessException e) {
29. throw new InternalError(e.toString());
30. } catch (InstantiationException e) {
31. throw new InternalError(e.toString());
32. } catch (InvocationTargetException e) {
33. throw new InternalError(e.toString());
34. }
35. }
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)做了以下几件事.
(1)根据参数loader和interfaces调用方法 getProxyClass(loader, interfaces)创建代理类$Proxy0.$Proxy0类 实现了interfaces的接口,并继承了Proxy类.
(2)实例化$Proxy0并在构造方法中把DynamicSubject传过去,接着$Proxy0调用父类Proxy的构造器,为h赋值,如下:
Java代码 [图片上传失败...(image-c01aff-1556796566845)]
1. class Proxy{
2. InvocationHandler h=null;
3. protected Proxy(InvocationHandler h) {
4. this.h = h;
5. }
6. ...
7. }
3.$Proxy源码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements IGamePlayer{
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode",
new Class[0]);
m3 = Class.forName("com.ml.test.GamePlayer").getMethod("login",
new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString",
new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
}
@Override
public final boolean equals(Object obj) {
try {
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
.booleanValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void login() {
try {
super.h.invoke(this, m3, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}