JDK动态代理
代理类根据业务实现类的对象和方法名动态的创建一个代理类的class文件并被字节码引擎执行,然后通过该代理类对象进行方法的调用。
代码实现
/** * @author zhang-jian */ public interface Test { /** * 测试方法 */ void printResult(); } /** * @author zhang-jian */ public class TestImpl implements Test { @Override public void printResult() { System.out.println("printResulting....."); } } /** * @author zhang-jian * @des jdk动态代理实现类 */ public class JdkDyProxy implements InvocationHandler { Object object; public Object getObject(Object object) { this.object = object; return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try { System.out.println("预处理----"); result = method.invoke(object, args); System.out.println("调用后处理----"); } catch (Exception e) { } return result; } public static void main(String[] args) { JdkDyProxy proxy = new JdkDyProxy(); Test object = (Test)proxy.getObject(new TestImpl()); object.printResult(); } } //测试结果如下 预处理---- printResulting..... 调用后处理----
在使用时,首先创建一个业务实现类对象和一个代理类对象,然后定义接口引用(这里使用向上转型)并用代理对象.getObject(业务实现类对象)的返回值进行赋值。最后通过接口引用调用业务方法即可。(接口引用真正指向的是一个绑定了业务类的代理类对象,所以通过接口方法名调用的是被代理的方法们)
Cglib动态代理
Jdk动态代理对业务实现类的要求是需要继承接口,而cglib不需要,cglib的原理是对指定的业务类实现子类,并覆盖其中的业务方法,实现代理,所以不能对final类进行代理。
代码实现
/** * @author zhang-jian */ public class TestImpl{ public void printResult() { System.out.println("printResulting....."); } } import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @author zhang-jian * @des jdk动态代理实现类 */ public class CglibDyProxy implements MethodInterceptor { Object object; public Object getObject(Object object) { this.object = object; Enhancer enhancer = new Enhancer(); enhancer.setCallback(this); enhancer.setSuperclass(object.getClass()); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("预处理---"); Object result = method.invoke(object, objects); System.out.println("调用后处理---"); return result; } public static void main(String[] args) { TestImpl test = new TestImpl(); CglibDyProxy proxy = new CglibDyProxy(); TestImpl object = (TestImpl)proxy.getObject(test); object.printResult(); } } //调用后结果 预处理--- printResulting..... 调用后处理---
创建业务类的代理类对象,通过代理类的.getObject(代理类对象)获得一个动态代理对象,最后通过动态代理对象调用被包装的函数。
比较:
Jdk动态代理是通过接口中的方法名,在动态的代理类中调用对业务类包装的方法。
Cglib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行实现。