准备
接口
public interface Person {
void eat();
void speak();
}
父类
public class Father {
public void sayHi(){
System.out.println("Hi im your father!");
}
}
子类
public class Son extends Father implements Person {
@Override
public void sayHi() {
super.sayHi();
System.out.println("这是儿子的say hi");
}
@Override
public void eat() {
System.out.println("eat");
}
@Override
public void speak() {
System.out.println("speak");
}
}
方法拦截
obj:被代理的对象实例。
method:正在被调用的方法对象。可以获取这个方法的有关信息。
objects:方法的参数数组。
methodProxy:方法的代理对象。实现对目标方法(method)的代理, 拦截和增强。
// 方法拦截 MethodInterceptor 接口,用于实现方法拦截器的功能
public class MymethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before method");
Object object = methodProxy.invokeSuper(o, objects);// (对象,参数)
System.out.println("after method");
return object;
}
}
运行
public class CjlibProxy {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();//可以动态生成一个代理类
enhancer.setSuperclass(Son.class);
enhancer.setCallback(new MymethodInterceptor());
Son son = (Son) enhancer.create();
son.eat();
System.out.println("======");
son.sayHi();
System.out.println("======");
son.speak();
}
}
效果
JDK 代理和 cjlib 代理
JDK
- 要求实现接口,代理接口提供的方法
- 通过
java.lang.reflect.Proxy
类和InvocationHandler
接口来实现,InvocationHandler.invoke
方法中实现逻辑
CJLIB
- 通过生成子类的方法实现代理,可以代理普通类,也注定不可以代理
final
修饰的类和方法 - 实现于字节码技术(ASM)
性能
由CJLB
singleton
单例模式的类,性能稍高(同一对象), 只需要生成一次子类,降低了生成对象的开销, 可以直接调用方法而不用像JDK一样使用反射.
但是只说结论就是耍流氓(在编译启动阶段JDK耗时低, CJLIB耗时高)