代理模式是指为其他对象提供一种代理,以控制对这个对象的访问。在客户端和莫表对象之前起一个中介的作用。作用呢就是保护和增强目标对象(AOP)。
静态代理是指通过手动代理的方式完成代理,被代理的类增加方法,代理类也需要增加方法,很明显违背了开闭原则。而动态代理则是在运行时生成代码,取消了对类的扩展限制,符合开闭原则。
- 静态代理
就好比租房。
有这样一个房子接口:
public interface Room{
//租房子
void findRoom();
}
一个刚毕业的大学生要租房子:
public class Stdent implements Room{
//租房子
public void findRoom(){
System.out.println("想要一个带阳台的房子");
}
}
这个时候他去中介租房子
public class Angency{
private Object obj;
public Angency(Object obj){
this.obj=obj;
}
public void findRoom(){
beforeFindRoom();
obj.findRoom();
afterFindRoom();
}
private void beforeFindRoom(){
System.out.println("中介带你看房子");
}
private void afterFindRoom(){
System.out.println("交钱!");
}
}
可以写个测试方法测试一下:
Angency an=new Angency(new Stdent ());
an.findRoom();
- 动态代理
动态代理有两种形式,jdk与cglib。
(1)jdk
同样是中介,利用反射去实现代理,这样实现呢,简单,但是效率低,毕竟空间和时间不可兼得嘛。
public class Angency implements InvocationHandler {
private Object obj;
public Object getInstance(Object target) throws Exception {
this.obj = target;
Class<?> clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeFindRoom();
Object obj = method.invoke(this.obj, args);
afterFindRoom();
return obj;
}
private void beforeFindRoom() {
System.out.println("中介带你看房子");
}
private void afterFindRoom() {
System.out.println("交钱!");
}
}
原理呢就是:先拿到被代理对象的引用,通过反射获取到他的接口,然后、JDK Proxy 类去生成一个实现所有接口的新类,动态生成代码,最后再编译执行。
(2)cglib
public class Angency implements MethodInterceptor {
public Object getInstance(Class<?> clazz) throws Exception {
Enhancer enhancer = new Enhancer();
// 要把哪个设置为即将生成的新类父类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
befbeforeFindRoomore();
Object obj = methodProxy.invokeSuper(o, objects);
afterFindRoom();
return obj;
}
private void beforeFindRoom() {
System.out.println("中介带你看房子");
}
private void afterFindRoom() {
System.out.println("交钱!");
}
}
Cglib 是通过动态继承目标对象实现的动态代理,使用 ASM 框架写 Class 字节码,实现更复杂,生成代理类效率低。而JDK Proxy 则是实现了被代理对象的接口,通过反射机制调用。二者都是在运行期生成代码的。
个人理解:代理模式将代理对象与调用的目标对象分离,降低了系统耦合性,可以保护增强目标对象,扩展性较好。但是代理模式增加了代码,代码一多,就降低理解性,代理对象与调用的目标对象分离,多走了一步,后台响应速度肯定会变慢。