目录
代理
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;
}
}
对比
- 二者都要创建代理类,以及代理类都要实现接口
- 静态代理要在编译前就需要代理类实现与被代理类相同的接口,并且直接在实现的方法中调用被代理类相应的方法
- 动态代理我们不知道要针对哪个接口、哪个被代理类创建代理类,因为它是在运行时被创建的
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方法