动态代理是使用反射机制对目标对象进行扩展,在运行时动态创建代理对象,从而实现对目标对象的增强。 Java有两种动态代理方式:

  1. 基于接口的动态代理:使用JDK中的Proxy类和InvocationHandler接口实现。
  2. 基于子类的动态代理:使用CGLIB库实现。

基于接口的动态代理:Proxy

Untitled

public interface Hello {

    void sayHello();

    void sayBye();

}
public class HelloImpl implements Hello {

    @Override
    public void sayHello() {
        System.out.println("Hello World!");
    }
    @Override
    public void sayBye() {
        System.out.println("Bye Bye!");
    }
}

定义一个InvocationHandler实现类,并在invoke方法中对目标方法进行增强:

可以判断方法名,不对sayBye方法增强,直接返回

public class InvocationHandler implements java.lang.reflect.InvocationHandler {

    private Object target;

    public InvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {
        if (method.getName().equals("sayBye")) {
            return method.invoke(target, args);
        }
        System.out.println("Before");
        Object result = method.invoke(target, args);
        System.out.println("After");
        return result;
    }

}

最后使用Proxy.newProxyInstance方法创建代理对象

public class Main {

    public static void main(String[] args) {
        Hello hello = new HelloImpl();
        InvocationHandler handler = new InvocationHandler(hello);
        Hello proxy = (Hello) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
        proxy.sayHello();
        proxy.sayBye();
    }

}

使用proxy对象调用方法时,会经过MyInvocationHandler的invoke方法进行增强,从而实现动态代理的效果。 这就是Java基于接口的动态代理实现原理,CGLIB原理类似,只是不依赖接口,直接对目标类进行子类化代理。

Untitled

Untitled

基于子类的动态代理:CGLib

Untitled

Untitled

Untitled

public class Hello {

    public void sayHello() {
        System.out.println("Hello World!");
    }

}

定义一个MethodInterceptor实现类,用于增强目标方法

public class HelloMethodInterceptor implements org.springframework.cglib.proxy.MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("Before");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("After");
        return result;
    }
}