动态代理的简单的实现:
//接口
interface Thing {
void drive();
}
//被代理类
class Car implements Thing {
@Override
public void drive() {
System.out.println("开始驾驶汽车!");
}
}
//代理类
class MyProxy implements InvocationHandler {
private Object object;
public MyProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
dosomethingBefore();
method.invoke(object,args);
dosomethingAfter();
return null;
}
private void dosomethingBefore() {
System.out.println("上车");
}
private void dosomethingAfter() {
System.out.println("下车");
}
}
//请求类
public class Driver {
public static void main(String[] args) {
Car car = new Car();
InvocationHandler handler = new MyProxy(car);
Thing thing = (Thing) Proxy.newProxyInstance(handler.getClass().getClassLoader(),car.getClass().getInterfaces(),handler);
thing.drive();
}
}
Spring的AOP(面向切面编程)使用的就是jdk的动态代理(默认)。可以使得我们在不改变原有程序执行顺序的基础上,在程序运行过程中的某一个切面插入一些我们想要的操作(日志,抛异常)。这在开发中操作数据库的时候比较常见,例如在事务开始之前或者之后输出一些东西。如果不使用AOP,则会使得程序变得非常冗余且可扩展性很差。
AOP的底层其实就是使用了jdk的动态代理,即请求类(Driver)在请求被代理类(Car)的时候,并不是直接去调用被代理类(Car)里面的方法,而是通过包裹在被代理类(Car)外面的一层代理类(MyProxy)去间接的调用。代理类(MyProxy)之中会有被代理类(Car,也就是Object)的对象,方便被代理类调用代理类的方法。通过这种设计,我们就可以在代理类(MyProxy)里面调用被代理类(Car)方法的前后插入一些我们想要的在实际操作之前或者之后进行的操作。
而代理类之所以能调用被代理类之中的方法使用到了java中的反射。