一、动态代理的作用
- 什么是代理
代理模式的意图是通过提供一个代理( Proxy )或者占位符来控制对该对象的访问。
- 使用的场景
在我们生活中,代理也是随处可见,其中中介就是一个很好的例子,把代理看做生活中的中介,将更加易于理解,试想一下,如果我们想租房或者买房的话通过中间是不是就可以让我们非常省心。
二、静态代理
在java中又两种代理模型,称之为静态代理和动态代理。为了保证与所代理的对象功能行为的一致性,代理类一般需要实现实体类所实现的同一个接口,以下即为一个最基本的代理模式的结构。
首先提供一个接口供实体类和代理类实现。
/**
* Created by jiangcheng on 2017/11/19.
*
* 抽象接口
*/
public interface Subject {
// 统一行为
void doSomeThing();
}
实体类:
public class RealSubject implements Subject {
@Override
public void doSomeThing() {
System.out.println(" RealSubject do somethings ");
}
}
代理类:
public class SubjectProxy implements Subject {
private RealSubject mRealSubject;
public SubjectProxy(RealSubject realSubject) {
mRealSubject = realSubject;
}
@Override
public void doSomeThing() {
// 这里就是所谓的aop 面向切面编程了, 你可以在调用实际功能之前或者之后做一些额外的处理
System.out.println(" RealSubject do somethings before");
mRealSubject.doSomeThing();
System.out.println(" RealSubject do somethings after");
}
}
测试类:
public class TestProxy {
public static void main(String args[]) {
Subject sub = new SubjectProxy(new RealSubject());
sub.doSomeThing();
}
}
结果:
从上面的例子可以看到调用的时候我们对实体类做了一层封装,从代码角度看,反而实现上更加复杂了,没有体现出代理模式的优势,其实代理模式的作用就是通过代理对象控制实体对象的访问,从而提高访问的安全性,而且可以在调用实体类的方法时做一些预处理和善后的工作,就是所谓的aop(面向切面编程)。这样就保证了实体类可以抛开复杂的业务逻辑而只去实现一些最纯粹的功能,提高了代码的可读性和灵活性。
三、动态代理
这个才是今天的重点,我们可以想一下,万一实现Subject接口的实体类不止一个呢,是不是需要创建SubjectProxy1、SubjectProxy2...这样的,那么这样就不是很灵活了呢,动态代理就能实现。
今天我们介绍JDK的动态代理,其实还有一种动态代理cglib,在web开发中用的比较多,所以就不展开讲述了,JDK中已经为我们提提供好了动态代理接口 InvocationHandler 我们只需要实现它即可创建一个动态代理类。如下:
/**
* Created by jiangcheng on 2017/11/19.
* 动态代理
*/
public class DynamicProxy implements InvocationHandler {
private Object mObject;
public DynamicProxy(Object object) {
mObject = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(" DynamicProxy is called");
return method.invoke(mObject, args);
}
/**
* 对外提供一个创建动态代理对象的方法
* @param object
* @return
*/
public static Object newProxyInstance(Object object) {
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(), new DynamicProxy(object));
}
}
调用:
public static void main(String args[]) {
// Subject sub = new SubjectProxy(new RealSubject());
// sub.doSomeThing();
// 这里利用的是强转(动态创建),所以当有RealSubject2、RealSubject3对象需要代理时,只需要创建一个代理类就行了
Subject subject = (Subject) DynamicProxy.newProxyInstance(new RealSubject());
subject.doSomeThing();
}
结果:
好了,静态代理和动态代理的基本使用和例子都写完了,但是InvocationHandler的invoke方法是由谁来调用的,代理对象是怎么生成的。invoke()方法中的一些参数的是什么呢,这就得等到下一part来讲述了。