目录

代理

JDK静态代理

就是两个类A ,B实现同一接口C,然后一个类B里面创建另一个类A的成员属性,调用方法C中调用前后进行出处理

// 被代理类 
public class Hello implements HelloInterface {


    @Override
    public void sayHello() {
        System.out.println("hello");
    }
}
// 接口
public interface HelloInterface {
    void sayHello();
}

// 代理类
public class HelloProxy implements HelloInterface {

    private HelloInterface helloInterface = new Hello();

    @Override
    public void sayHello() {
        System.out.println("before invoke sayHello");
        helloInterface.sayHello();
        System.out.println("after invoke sayHello");
    }

    public static void main(String[] args) {
        HelloProxy s = new HelloProxy();
        s.sayHello();
    }
}

JDK动态代理

// 被代理类
public class Hello implements HelloInterface {


    @Override
    public void sayHello() {
        System.out.println("hello");
    }
}
// 接口
public interface HelloInterface {
    void sayHello();
}
// 代理类
public class HelloProxyDynaic implements InvocationHandler {

    private Object object;

    public HelloProxyDynaic(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before invoke " + method.getName());
        method.invoke(object,args);
        System.out.println("before invoke " + method.getName());
        return null;
    }
}

对比

  1. 二者都要创建代理类,以及代理类都要实现接口
  2. 静态代理要在编译前就需要代理类实现与被代理类相同的接口,并且直接在实现的方法中调用被代理类相应的方法
  3. 动态代理我们不知道要针对哪个接口、哪个被代理类创建代理类,因为它是在运行时被创建的

JDK静态代理是通过直接编码创建的,而JDK动态代理是利用反射机制在运行时创建代理

CGLIB代理

  • 生成代理类的二进制字节码文件;
    • 加载二进制字节码,生成Class对象( 例如使用Class.forName()方法 );
  • 通过反射机制获得实例构造,并创建代理类对象
public class Client {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Hello.class); // 继承被代理类
        enhancer.setCallback(new HelloMethodInterceptor()); // 生成代理类对象
        Hello hello = (Hello) enhancer.create();  // 调用代理类中方法时会被我们实现的方法拦截器进行拦截
        hello.sayHello();
    }

}
public class Hello {

    public void sayHello() {
        System.out.println("hello");
    }
}

public class HelloMethodInterceptor implements MethodInterceptor {


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

代理类会为委托方法生成两个方法,一个是重写的 sayHello方法,另一个是CGLB$sayHello方法,我们可以看到它是直接调用父类的 sayHello方法