spring 动态代理如何选择

不及物动词 其他 16

回复

共3条回复 我来回复
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    Spring动态代理可以选择使用JDK动态代理或者CGLIB动态代理。具体选择哪种方式取决于被代理类是否实现了接口。

    1. JDK动态代理:JDK动态代理是基于接口的代理,它利用Java的反射机制来生成一个实现代理接口的匿名类,可以代理实现了接口的任何类。使用JDK动态代理时,需要被代理类实现一个接口,并且代理类要实现InvocationHandler接口,并且重写invoke()方法。JDK动态代理的优点是生成的代理类相对轻量级,不需要额外的库支持。

    2. CGLIB动态代理:CGLIB动态代理是基于类的代理,它通过生成一个被代理类的子类来实现代理,这种方式不需要被代理类实现接口。使用CGLIB动态代理时,被代理类不能是final类,代理类会继承被代理类,并重写其中的方法来实现代理逻辑。CGLIB动态代理的优点是可以代理没有实现接口的类,生成的代理类更加强大,可以代理类中的final方法。

    在Spring中,默认情况下,Spring会根据被代理的类是否实现接口来选择使用JDK动态代理还是CGLIB动态代理。如果被代理的类实现了接口,Spring会使用JDK动态代理;如果被代理的类没有实现接口,Spring会使用CGLIB动态代理。当然,也可以通过配置来强制选择使用某一种代理方式。

    总之,选择Spring动态代理的方式取决于被代理类的具体情况。如果被代理类实现了接口,可以选择使用JDK动态代理;如果被代理类没有实现接口,可以选择使用CGLIB动态代理。

    1年前 0条评论
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    Spring提供了两种动态代理的选择:基于JDK动态代理和基于CGLIB动态代理。

    1. 基于JDK动态代理:
      JDK动态代理是通过Java的反射机制实现的,它要求被代理的对象必须实现一个或多个接口。在使用JDK动态代理时,Spring使用JDK的Proxy类来创建代理对象。具体实现是通过实现InvocationHandler接口并覆盖它的invoke方法来实现的。

    使用JDK动态代理的优点包括:

    • 程序代码更简洁,代理类的生成不需要额外的库支持。
    • JDK动态代理是Java官方提供的标准库,具有很好的兼容性和稳定性。

    使用JDK动态代理的缺点包括:

    • 被代理的对象必须实现一个或多个接口,如果没有接口则无法使用JDK动态代理。
    • JDK动态代理只能对实现了接口的类进行代理,对于没有实现接口的类无法代理。
    1. 基于CGLIB动态代理:
      CGLIB动态代理是通过创建目标类的子类来实现的,不需要被代理的对象实现接口。CGLIB动态代理使用字节码生成技术,通过修改字节码来生成子类,从而实现代理功能。

    使用CGLIB动态代理的优点包括:

    • 不需要被代理对象实现接口,可以对任何类进行代理。
    • 可以代理没有实现接口的类。

    使用CGLIB动态代理的缺点包括:

    • 使用CGLIB动态代理会增加额外的类加载和字节码生成的开销,相比JDK动态代理会略微降低性能。
    • 如果目标类中的方法被final修饰,CGLIB无法代理。

    在选择使用JDK动态代理还是CGLIB动态代理时,可以根据以下几个因素进行权衡:

    • 如果被代理对象有接口实现,且对性能要求较高,可以选择JDK动态代理。
    • 如果被代理对象没有接口实现,或者对性能要求相对较低,可以选择CGLIB动态代理。
    • 可以根据实际情况进行测试和比较,选择最适合的动态代理方式。
    1年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    Spring动态代理可以选择两种方式:JDK动态代理和CGLIB动态代理。

    1. JDK动态代理:
      JDK动态代理是基于接口的动态代理,它通过反射机制在运行时创建代理对象。JDK动态代理要求被代理的目标类必须实现一个接口,代理对象会实现该接口,并通过代理对象调用目标类的方法。JDK动态代理使用java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler这两个类来实现。

    使用JDK动态代理的步骤如下:

    1. 创建一个实现InvocationHandler接口的类,用于增强目标类的方法。
    2. 通过Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法创建代理对象。
    3. 调用代理对象的方法。

    例如,以下是使用JDK动态代理增强HelloService接口的示例代码:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class JDKDynamicProxyDemo {
        public static void main(String[] args) {
            HelloService helloService = new HelloServiceImpl();
            InvocationHandler handler = new MyInvocationHandler(helloService);
            HelloService proxy = (HelloService) Proxy.newProxyInstance(HelloService.class.getClassLoader(),
                    new Class[]{HelloService.class}, handler);
            proxy.sayHello("World");
        }
    }
    
    interface HelloService {
        void sayHello(String name);
    }
    
    class HelloServiceImpl implements HelloService {
        public void sayHello(String name) {
            System.out.println("Hello, " + name);
        }
    }
    
    class MyInvocationHandler implements InvocationHandler {
        private Object target;
    
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
    
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Before method call");
            Object result = method.invoke(target, args);
            System.out.println("After method call");
            return result;
        }
    }
    
    1. CGLIB动态代理:
      CGLIB动态代理是基于类的动态代理,它通过继承目标类创建代理对象。CGLIB动态代理不要求被代理的目标类实现接口,而是通过继承目标类的方式进行代理。CGLIB动态代理使用net.sf.cglib.proxy.Enhancernet.sf.cglib.proxy.MethodInterceptor这两个类来实现。

    使用CGLIB动态代理的步骤如下:

    1. 创建一个类来实现MethodInterceptor接口,用于增强目标类的方法。
    2. 创建Enhancer对象,并设置父类和回调方法。
    3. 调用Enhancer.create()方法创建代理对象。
    4. 调用代理对象的方法。

    例如,以下是使用CGLIB动态代理增强HelloService类的示例代码:

    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class CGLIBDynamicProxyDemo {
        public static void main(String[] args) {
            HelloService helloService = new HelloService();
            MethodInterceptor handler = new MyMethodInterceptor();
            HelloService proxy = (HelloService) Enhancer.create(HelloService.class, handler);
            proxy.sayHello("World");
        }
    }
    
    class HelloService {
        public void sayHello(String name) {
            System.out.println("Hello, " + name);
        }
    }
    
    class MyMethodInterceptor implements MethodInterceptor {
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("Before method call");
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("After method call");
            return result;
        }
    }
    

    选择使用JDK动态代理还是CGLIB动态代理要根据具体的需求和场景来决定。JDK动态代理更加轻量级,适用于对接口进行代理的情况;而CGLIB动态代理适用于对类进行代理的情况,能够代理那些没有实现接口的类。

    1年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部