一、介绍
对其他对象提供一种代理以控制对这个对象的访问。
它有如下角色:
Subject:一个抽象的角色,是一个接口。
RealSubject:真实对象,是对接口的实现。
Proxy:代理对象,里面持有被代理对象(RealSubject)的引用,所以操作代理对象时从而可以操作真实对象,并且在操作真实对象之前可以可以加一些其他的操作,比如对真实对象的权限访问等等。
下面是代理模式的UML类图:
二、分类
- 静态代理
- 动态代理
三、实现
1、静态代理的实现
public interface Subject {
void doSomething();
}
public class SubjectImpl implements Subject {
@Override
public void doSomething() {
System.out.println("do something ……");
}
}
public class Proxy implements Subject{
private final Subject subject = new SubjectImpl();
@Override
public void doSomething() {
System.out.println("before doing");
subject.doSomething();
System.out.println("after doing");
}
}
public class ProxyTest {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.doSomething();
}
}
这种实现方式在程序执行之前就已经由我们写好的代理类在执行之前就已经知道了要代理的对象的是谁,而不是由程序自动生成的,这就是指的静态。这样的实现方式的缺点就是不容易维护,比如接口发生了改变,添加或者减少了方法,那么就需要真实对象和代理对象都发生改动。
2、动态代理的实现
动态代理实现有两种方式,一种是jdk实现,另一只就是cglib实现。
jdk的实现:
1:创建一个类实现InvocationHandler接口,并且重写invoke方法。
2:调用Proxy的newProxyInstance创建一个代理类。
3:用代理类调用需要的方法。
public interface Subject {
void doSomething();
}
public class SubjectImpl implements Subject {
@Override
public void doSomething() {
System.out.println("do something ……");
}
}
public class SubjectProxy {
public static Object proxy(){
Object object = Proxy.newProxyInstance(SubjectImpl.class.getClassLoader(),
SubjectImpl.class.getInterfaces(), new MyInvocationHandler());
return object;
}
private static class MyInvocationHandler implements InvocationHandler {
private final Subject subject = new SubjectImpl();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before doing");
Object object = method.invoke(subject, args);
System.out.println("after doing");
return object;
}
}
}
public class ProxyTest {
public static void main(String[] args) {
Subject subject = (Subject) SubjectProxy.proxy();
subject.doSomething();
}
}
cglib实现:
1:创建一个类实现MethodInterceptor接口并且重写Interpect方法。
2:创建Enhandcer设置父类、回调创建代理类
3:用代理类调用需要的方法。
public class Subject {
public void doSomething(){
System.out.println("do something ……");
}
}
public class SubjectProxy {
public static Object proxy(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Subject.class);
enhancer.setCallback(new MyInterceptor());
return enhancer.create();
}
private static class MyInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before doing");
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("after doing");
return object;
}
}
}
public class ProxyTest {
public static void main(String[] args) {
Subject subject = (Subject) SubjectProxy.proxy();
subject.doSomething();
}
}
jdk实现和cglib实现对比:
jdk实现 | cglib实现 |
利用用反射实现 | 利用asm开源包通过字节码重组实现 |
目标对象必须实现接口 | 目标对象不需要实现接口,但是不能代理final修饰的方法 |