本文主要是介绍动态代理(JDK CGLIB),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
静态代理,一个代理类只能代理一个接口,好处的简单、好实现、好理解,坏处呢,举个例子,我们知道Mybatis逆向工程会生成N多个Mapper接口文件,如果每个Mapper接口都造一个代理类出来,然后呢,每个代理类做的事情又都是一样的——获取session、解析crud语句、执行crud、处理结果、结束session。
难道我们对此就束手无策了吗?不,使用动态代理,我们可以只造一个轮子就能代理everything。
动态代理分两种:Java动态代理 和 CGLib,其中Java动态代理只能代理实现了接口的类,而CGLib则可以代理一个没有实现任何接口的类。
1 JDK动态代理
实现InvocationHandler并重写invoke方法。
public interface Hello {void say(String name);
}
public class HelloImpl implements Hello {@Overridepublic void say(String name) {System.out.println("Hello! " + name);}
}
public class DynamicProxy implements InvocationHandler {//能代理任意一个类private Object target;public DynamicProxy(Object target) {this.target = target;}/*** 能接收任意数量和类型的参数、任意的返回值、任意的异常抛出* @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object result = method.invoke(target, args);after();return result;}private void before() {System.out.println("Before");}private void after() {System.out.println("After");}
测试一下:
public class Test {public static void main(String[] args) {Hello hello = new HelloImpl();DynamicProxy dynamicProxyHandler = new DynamicProxy(hello);Hello helloProxy = (Hello) Proxy.newProxyInstance(hello.getClass().getClassLoader(),hello.getClass().getInterfaces(),dynamicProxyHandler);helloProxy.say("biglong");}
}
打印出来是:
Before
Hello! biglong
After
——————————————— 割以咏志 ———————————————————————
以上Proxy.newProxyInstance的方法还是有点复杂,需要传入3个参数:
参数1:ClassLoader
参数2:该实现类的所有接口
参数3:动态代理对象
我们可以简化一下:
public class DynamicProxy2 implements InvocationHandler {...@SuppressWarnings("unchecked")public <T> T getProxy() {return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}...
}
测试下:
public class Test2 {public static void main(String[] args) {Hello hello = new HelloImpl();DynamicProxy2 dynamicProxy2 = new DynamicProxy2(hello);Hello helloProxy = dynamicProxy2.getProxy();helloProxy.say("biglong");}
}
输出跟上面一样。
2 CGLib动态代理
如果一个类没有实现任何接口,以上JDK动态代理就成了废物,此时CGLib粉墨登场,CGLib可以代理没有接口的类——我们的Spring框架的AOP就用了这个。
public class CGLibProxy implements MethodInterceptor {//单例模式(懒汉)private static CGLibProxy instance = new CGLibProxy();public static CGLibProxy getInstance() {return instance;}private CGLibProxy() {}@SuppressWarnings("unchecked")public <T> T getProxy(Class<T> cls) {return (T) Enhancer.create(cls, this);}@Overridepublic Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {before();Object result = proxy.invokeSuper(target, args);after();return result;}private void before() {System.out.println("Before");}private void after() {System.out.println("After");}
}
测试一下:
public class Test {public static void main(String[] args) {HelloImpl helloProxy = CGLibProxy.getInstance().getProxy(HelloImpl.class);helloProxy.say("biglong");}
}
这篇关于动态代理(JDK CGLIB)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!