我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。
代理模式是java常用的设计模式,代理类与委托类具有同样的接口,就好像明星的经纪人一样,有什么事情不直接 找到本人,需要先通过经纪人联系。
代理模式结构图(图片来自《大话设计模式》):
一:静态代理:
静态代理:由程序员创建或者特定工具自动生成源码,也就是编译期已经将接口,被代理类,代理类等确定下来,在程序运行之前代理类的class文件已经生成
实现demo
/**
* 人接口
*/
public interface Person {
//人具有工作的性质
public void work();
}
/**
* 明星是人的一种,具有唱歌的工作
*/
public class SuperStar implements Person {
public String name;
public SuperStar(String name) {
this.name = name;
}
@Override
public void work() {
System.out.println(name+"唱歌");
}
}
/**
* 经纪人的工作就是代理明星,邀请明星进行唱歌
*/
public class SuperStarProxy implements Person{
//被代理的明星
private SuperStar sp;
public SuperStarProxy(SuperStar sp) {
this.sp = sp;
}
@Override
public void work() {
//真正的明星进行工作
sp.work();
}
}
最常规的用法的就是在Spring中的面向切面编程(AOP),我们能在一个切点之前执行一些操作,在一个切点之后执行一些操作,这个切点就是一个个方法。这些方法所在类肯定就是被代理了,在代理过程中切入了一些其他操作。
二:动态代理
代理类是在运行时创建则成为动态代理,详见下面demo
public class MyInvocationHandler<T> implements InvocationHandler {
T target;
public MyInvocationHandler(T target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在执行方法之前插入一些操作
System.out.println("before");
Object result = method.invoke(target,args);
//在执行方法之后插入一些操作
System.out.println("after");
return result;
}
}
class ProxyTest {
public static void main(String[] args) {
//创建实例对象jay
SuperStar superStar = new SuperStar("jay");
//创建一个与代理相关的handler
MyInvocationHandler<Person> personMyInvocationHandler = new MyInvocationHandler<>(superStar);
//创建一个代理对象(经纪人)来代理jay
Person superStarProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, personMyInvocationHandler);
//代理执行上述方法
superStarProxy.work();
}
}