代理模式与动、静态代理
最近正在纠结考研还是找工作,数学与数据结构都不想学,烦心之下,学点jvav冷静一下,本篇博文主要是讲代理模式以及java中如何用反射机制实现动态代理,大部分瞎比分析都在代码注释里面哈!
代理模式的概念:
Proxy Pattern,是23种经典模式种的一种。
在调用方与被调用方中间增加一层代理对象,从而实现调用方与被调用方之间的解耦。
为目标对象提供一个代理,这个代理可以控制对目标对象的访问,外界不用直接访问目标对象,而是访问代理对象,代理对象再调用目标对象。且代理对象中可以添加监控和审查处理。
计算机里,没有什么问题是加一层解决不了的, 如果有的话,只会是加一层后引起新的问题。(啊哈哈哈,wdnmd)
静态代理
代理对象持有目标对象的句柄。(被代理的对象会被当做一个成员变量放在代理对象里面)
所有调用目标对象的方法,都改用调用代理对象的方法。
对每一个方法都需要静态编码(理解简单,但是代码繁琐)
public interface Subject {
public void request();
}
public class SubjectImpl implements Subject{
public void request() {
// TODO Auto-generated method stub
System.out.println("subjectimpl");
}
}
public class StaticProxy implements Subject{
private Subject subject;
public StaticProxy(Subject subject) {
this.subject = subject;
}
public void request() {
// TODO Auto-generated method stub
System.out.println("preprocess");
subject.request();
System.out.println("afterprocess");
}
}
public class StaticProxyDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
SubjectImpl s = new SubjectImpl();
StaticProxy sp = new StaticProxy(s);
sp.request();
}
}
动态代理
为了避免对每个方法进行包装,动态代理被设计而出。
对目标对象的方法每次被调用,进行动态拦截
动态代理流程图
首先是被代理对象的接口
public interface Subject {
public void request();
}
被代理对象
public class SubjectImpl implements Subject{
public void request() {
// TODO Auto-generated method stub
System.out.println("subjectimpl");
}
}
代理处理器,其中的invoke方法里,有代理时需要进行的操作。
分为before与after以及around等操作。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//实现了InvocationHandler接口,
public class ProxyHandler implements InvocationHandler {
//将Subject接口作为一个内部成员变量,组合起来
private Subject subject;
//定义一个构造器,方便Subject的子类进行赋值传入
public ProxyHandler(Subject subject){
this.subject = subject;
}
//实现InocationHandler接口,需要重写invoke方法,该方法由三个参数
/**
*
* @param proxy 代理对象
* @param method 调用的方法
* @param args 形参
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass().getName());
System.out.println("before");
//这句话相当于是 Object result = xx类.xx方法(args);只不过是通过反射来做的。
Object result = method.invoke(subject,args);
System.out.println("after");
return result;
}
}
main中生成代理对象,并且完成调用
import java.lang.reflect.Proxy;
public class DynamicPoxyDemo {
public static void main(String[] args) {
//创造一个实现了Subject接口的对象
SubjectImpl realSubject = new SubjectImpl();
//将上面的对象交给代理处理器对象接管。
//代理处理器对象
ProxyHandler handler = new ProxyHandler(realSubject) ;
//代理处理器对象再交给代理对象接管。Proxy对象生成实例时候需要三个参数:
//1.生成代理对象使用哪一个类加载器
//2.生成哪一个对象的对象代理,通过接口来指定
//3.生成的代理对象的方法里需要干什么事情,由开发人员来编写Handler接口实现来指定。
//动态生成代理对象
Subject proxySubject =
(Subject) Proxy.newProxyInstance(
SubjectImpl.class.getClassLoader(),
SubjectImpl.class.getInterfaces(),handler
);
proxySubject.request();
System.out.println(proxySubject.getClass().getName());
}
}
附带两张图,方便食用。