【Java基础】——JDK动态代理VSCGLIB动态代理

约定不等于承诺〃 2022-05-30 06:24 338阅读 0赞

前提

  1. 之前分别写过[代理模式][Link 1]和[反射机制][Link 2],这篇文章主要总结一下两者结合使用的产物动态代理。

JDK动态代理

  1. JDK实现动态代理需要实现类通过实现接口定义业务方法完成。

实现方式

  1. public interface HelloService {
  2. public void sayHello(String name);
  3. }
  4. public class HelloServiceImpl implements HelloService {
  5. @Override
  6. public void sayHello(String name) {
  7. System.err.println("hello"+name);
  8. }
  9. }
  10. import java.lang.reflect.InvocationHandler;
  11. import java.lang.reflect.Method;
  12. import java.lang.reflect.Proxy;
  13. /** * @author 贾文静-JDK实现动态代理 * @DESCRIPTION:$ * @Date: **/
  14. public class HelloServiceProxy implements InvocationHandler {
  15. // 真实服务对象
  16. private Object target;
  17. /** * 绑定委托对象并返回代理对象 * @param target * @return */
  18. public Object bind(Object target) {
  19. this.target = target;
  20. // 获取代理对象
  21. return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
  22. }
  23. /** * 通过代理对象调用方法首先进入这个方法 * @param proxy * @param method * @param args * @return * @throws Throwable */
  24. @Override
  25. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  26. System.err.println("#####我是jdk代理");
  27. Object result = null;
  28. System.err.println("我准备说Hello。");
  29. result = method.invoke(target, args);
  30. System.err.println("我说Hello了");
  31. return result;
  32. }
  33. }
  34. /** * @author 贾文静 * @DESCRIPTION:$ * @Date: **/
  35. public class HelloServiceMain {
  36. public static void main(String[] args) {
  37. // 创建代理对象
  38. HelloServiceProxy helloServiceProxy = new HelloServiceProxy();
  39. // 委托代理对象执行HelloService
  40. HelloService proxy = (HelloService) helloServiceProxy.bind(new HelloServiceImpl());
  41. //本质调用的代理对象的involve方法
  42. proxy.sayHello("张三");
  43. }
  44. }

步骤
1、代理对象和真实对象进行绑定,绑定过程中代理对象获取到真实对象,即代理类中target
2、代理对象调用方法实际执行的是invoke方法,在invoke利用反射机制调用到HelloServiceImpl类的方法

CGLIB动态代理:

  1. JDK动态代理有一个缺陷就是必须有接口,如果没有接口的方法又该如何实现动态代理?即也就是CGLIB方式的动态代理所提供的方式。
  2. CGLIB采用底层的字节码技术,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,并在子类中采用方法拦截技术拦截所有调用父类方法的调用,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

实现方式

  1. //添加依赖
  2. <dependency>
  3. <groupId>cglib</groupId>
  4. <artifactId>cglib</artifactId>
  5. <version>3.2.4</version>
  6. </dependency>
  7. import net.sf.cglib.proxy.Enhancer;
  8. import net.sf.cglib.proxy.MethodInterceptor;
  9. import net.sf.cglib.proxy.MethodProxy;
  10. import java.lang.reflect.Method;
  11. /** * @author 贾文静 * @DESCRIPTION:$ * @Date: **/
  12. public class HelloServiceCgLib implements MethodInterceptor {
  13. private Class target;
  14. public Object getInstance(Class target) {
  15. this.target = target;
  16. Enhancer enhancer = new Enhancer();
  17. enhancer.setSuperclass(this.target);
  18. enhancer.setCallback(this);
  19. return enhancer.create();
  20. }
  21. @Override
  22. public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
  23. System.out.println("我是CGLIB的动态代理");
  24. System.out.println("我准备说hello");
  25. Object returnObj = proxy.invokeSuper(object, objects);
  26. System.out.println("我说过hello了");
  27. return returnObj;
  28. }
  29. }
  30. public class Hello {
  31. public void sayHello(String name) {
  32. System.out.println("hello"+name);
  33. }
  34. }
  35. public class CGLib {
  36. public static void main(String[] args) {
  37. HelloServiceCgLib helloServiceCgLib = new HelloServiceCgLib();
  38. Hello proxy = (Hello) helloServiceCgLib.getInstance(Hello.class);
  39. proxy.sayHello("贾文静");
  40. }
  41. }

JDK动态代理VSCGLIB动态代理

  1. CGLIb创建动态代理对象相比JDK创建的动态代理对象性能高很多,但是CGLIb在创建对象的时所花费的时间比JDK多,所以对于单例对象,不用频繁创建的使用CGLIb效率会更好一些,比如需要延迟加载的地方使用CGLIb,相反使用JDK动态代理更合适。因为CGLIb是动态创建子类,对于final方法,无法进行代理。在会更合适一些。
  2. **如有错误之处还请各位大神指出,小编不胜感激!!!**

发表评论

表情:
评论列表 (有 0 条评论,338人围观)

还没有评论,来说两句吧...

相关阅读

    相关 代理-jdk动态代理

    1、基于接口的实现,要jdk动态代理的类必须要实现一个接口; 2、中介类:实现了InvocationHandler,并重写这个接口的 方法(public Object inv