动态代理

Jdk 动态代理

Jdk动态代理,利用反射,实现 InvocationHandler 接口。Jdk 动态代理需要实现类通过接口定义业务方法,也就是说,委托类必须实现一个定义了业务方法的接口,在接口里约定需要代理的方法,并且只能对接口里约定的方法实现代理。由于需要委托类实现一个接口,这是一个局限性。

动态代理_第1张图片
Jdk 代理类图
  • Subject 类
public interface Subject {
    void doSomething();
}
  • RealSubject 类
public class RealSubject implements Subject {
    @Override
    public void doSomething() {
        System.out.println("do something");
    }
}
  • Jdk 代理
public class JdkProxy implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result;
        System.out.println("jdk proxy before");
        result = method.invoke(target, args);
        System.out.println("jdk proxy after");
        return result;
    }
}
  • Jdk 代理测试
public class JdkProxyTest {
    @Test
    public void testJdkProxy() {
        RealSubject realSubject = new RealSubject();
        Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new JdkProxy(realSubject));
        subject.doSomething();
    }
}

运行结果:
jdk proxy before
do something
jdk proxy after

Cglib 动态代理

Cglib 代理是针对类来实现代理的,并不要求委托类必须实现接口,它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,采用的是继承的方式。由于是采用继承的方式,所以用 Cglib 实现的代理类是不能处理被final关键字修饰的方法的。

动态代理_第2张图片
Cglib 代理类图
  • Cglib 代理
public class CglibProxy implements MethodInterceptor {
    public Object getInstance(Class clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result;
        System.out.println("cglib proxy before");
        result = methodProxy.invokeSuper(o, objects);
        System.out.println("cglib proxy after");
        return result;
    }
}

在上文中可以看到,代理对象的生成过程是由 Enhancer 类来实现的,大概步骤是:

  1. 生成代理类 Class 的二进制字节码;
  2. 通过 Class.forName 加载二进制字节码,生成Class对象;
  3. 通过反射机制获取实例构造,并初始化代理类对象。

intercept() 方法拦截目标类方法的调用,o 表示目标类的实例,method 为目标类方法的反射对象,objects 为方法的动态入参,methodProxy 为代理类实例。

  • Cglib 代理测试
public class CglibProxyTest {
    @Test
    public void testCglibProxy() {
        RealSubject realSubject = (RealSubject) new CglibProxy().getInstance(RealSubject.class);
        realSubject.doSomething();
    }
}

运行结果:
cglib proxy before
do something
cglib proxy after

你可能感兴趣的:(动态代理)