文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。
JDK 动态代理
代理模式是常用的 JAVA 设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 JDK 动态代理是 java.lang.reflect.* 包提供的方式,但是必须借助一个或多个接口才能产生代理对象。
类 |
说明 |
java.lang.reflect.Proxy |
用来获取动态代理对象 |
java.lang.reflect.InvocationHandler |
用来约束调用者实现 |
定义接口 IHelloWorld
public interface IHelloWorld {
public void sayHelloWorld();
}
定义实现类 HelloWorldImpl
public class HelloWorldlmpl implements IHelloWorld {
@Override
public void sayHelloWorld() {
System.out.println("Hello World !");
}
}
定义代理类 JdkProxy
public class JdkProxy implements InvocationHandler {
public Object target = null;
public Object build(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("先处理~!!");
Object obj = method.invoke(target, args);
System.out.println("后处理~!!");
return obj;
}
- 第一步,建立代理对象和真实对象的关系。
Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
参数 |
说明 |
target.getClass().getClassLoader() |
类加载器 |
target.getClass().getInterfaces() |
动态代理的下挂接口,即 IHelloWorld |
this |
实现方法逻辑的动态代理类,即 JdkProxy 本身 |
- 第二步,实现代理的逻辑方法。
invoke(Object proxy, Method method, Object[] args)
参数 |
说明 |
proxy |
代理对象,build 方法生成的对象 |
method |
当前正在调度的方法 |
args |
调度方法的参数 |
Object obj = method.invoke(target, args);
实现和输出结果
JdkProxy example = new JdkProxy();
IHelloWorld helloWorld = (IHelloWorld) example.build(new HelloWorldImpl());
helloWorld.sayHelloWorld();
先处理~!!
Hello World !!
后处理~!!
CGLIB 动态代理
CGLIB 是一个强大的,高性能,高质量的 Code 生成类库。它可以在运行期扩展 Java 类与实现 Java 接口。其底层是通过小而快的字节码处理框架 ASM(http://forge.ow2.org/projects/asm,使用 BSD License)来转换字节码并生成新的类。大部分功能实际上是 asm 所提供的,CGLIB 只是封装了 asm,简化了 asm 的操作,实现了在运行期动态生成新的 class。
类 |
说明 |
net.sf.cglib.core |
底层字节码处理类,他们大部分与 ASM 有关系 |
net.sf.cglib.transform |
编译期或运行期类和类文件的转换 |
net.sf.cglib.proxy |
实现创建代理和方法拦截器的类 |
net.sf.cglib.reflect |
实现快速反射和C#风格代理的类 |
net.sf.cglib.util |
集合排序工具类 |
net.sf.cglib.beans |
JavaBean 相关的工具类 |
直接定义类 HelloWorldImpl
public class HelloWorldlmpl {
public void sayHelloWorld() {
System.out.println("Hello World !");
}
}
定义代理类 CglibProxy
public class CglibProxy implements MethodInterceptor {
public Object getProxy(Class cls) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(cls);
enhancer.setCallback(this);
enhancer.setClassLoader(cls.getClassLoader());
return enhancer.create();
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("先处理~!!");
Object obj = methodProxy.invokeSuper(proxy, args);
System.out.println("后处理~!!");
return obj;
}
}
- 第一步,建立代理对象和真实对象的关系。
enhancer.setSuperclass(cls);
enhancer.setCallback(this);
enhancer.setClassLoader(cls.getClassLoader());
return enhancer.create();
参数 |
说明 |
enhancer.setSuperclass(cls) |
设置要代理的目标类,以扩展它的功能 |
enhancer.setCallback(this) |
设置单一回调对象,在回调中拦截对目标方法的调用 |
enhancer.setClassLoader(cls.getClassLoader()) |
设置类装载器 |
enhancer.create() |
创建代理对象 |
- CGLIB 包提供了一些专门的回调(callback)类型
类型 |
说明 |
net.sf.cglib.proxy.FixedValue |
为提高性能,FixedValue 回调对强制某一特别方法返回固定值是有用的。 |
net.sf.cglib.proxy.NoOp |
把对方法调用直接委派到这个方法在父类中的实现。 |
net.sf.cglib.proxy.LazyLoader |
当实际的对象需要延迟装载时,可以使用 LazyLoader 回调。一旦实际对象被装载,它将被每一个调用代理对象的方法使用。 |
net.sf.cglib.proxy.Dispatcher |
Dispathcer 回调和 LazyLoader 回调有相同的特点,不同的是,当代理方法被调用时,装载对象的方法也总要被调用。 |
net.sf.cglib.proxy.ProxyRefDispatcher |
ProxyRefDispatcher 回调和 Dispatcher 一样,不同的是,它可以把代理对象作为装载对象方法的一个参数传递。 |
- 第二步,实现代理的逻辑方法。
intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
参数 |
说明 |
proxy |
代理对象 |
method |
被代理的方法 |
args |
该方法的参数数组 |
methodProxy |
不是原始的 method,以提高性能 |
实现和输出结果
CglibProxy cglibProxy = new CglibProxy();
HelloWorldImpl hw = (HelloWorldImpl) cglibProxy.getProxy(HelloWorldImpl.class);
hw.sayHelloWorld();
先处理~!!
Hello World !!
后处理~!!
参考资料
http://blog.csdn.net/zhoudaxia/article/details/30591941
网友评论