spring的动态代理是如何实现的

fiy 其他 13

回复

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

    Spring的动态代理是通过底层的JDK动态代理和CGLIB动态代理来实现的。具体来说,Spring会根据被代理对象的接口或者类,决定使用哪一种方式来生成代理类。

    1、JDK动态代理
    JDK动态代理是基于接口的代理,它利用Java的反射机制动态地生成一个实现了被代理接口的代理类。JDK动态代理要求被代理的对象必须实现一个或多个接口。当调用被代理接口的方法时,代理类会通过调用InvocationHandler的invoke方法来触发相应的拦截逻辑。在invoke方法中,可以对方法进行增强、记录日志等操作。JDK动态代理的生成过程主要包括以下步骤:
    (1) 定义一个实现InvocationHandler接口的代理类,实现invoke方法来实现拦截逻辑;
    (2) 使用Proxy类的newProxyInstance方法动态生成代理对象。

    2、CGLIB动态代理
    CGLIB动态代理是基于类的代理,它通过继承被代理类来生成一个子类,并重写其中的方法进行拦截。相比JDK动态代理,CGLIB动态代理不要求被代理对象实现接口,因此可以对任意的类进行代理。当调用被代理类的方法时,代理类会通过调用MethodInterceptor的intercept方法来实现拦截逻辑。在intercept方法中,可以对方法进行增强、记录日志等操作。CGLIB动态代理的生成过程主要包括以下步骤:
    (1) 定义一个实现MethodInterceptor接口的代理类,实现intercept方法来实现拦截逻辑;
    (2) 使用Enhancer类的create方法动态生成代理对象。

    在使用Spring的动态代理时,可以通过配置文件或者注解的方式来指定使用哪一种代理方式。通常情况下,如果被代理对象实现了接口,Spring会使用JDK动态代理;如果被代理对象没有实现接口,Spring会使用CGLIB动态代理。但是也可以通过配置来强制使用某一种代理方式。

    总结:Spring的动态代理是通过底层的JDK动态代理和CGLIB动态代理来实现的,根据被代理对象的接口或者类的不同,决定使用哪一种方式来生成代理类。JDK动态代理适用于基于接口的代理,CGLIB动态代理适用于基于类的代理。

    1年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    Spring的动态代理是通过Java的反射机制实现的。动态代理允许在运行时创建代理对象,这些代理对象可以在被调用时拦截方法调用并执行额外的逻辑。

    Spring使用了两种类型的动态代理:基于JDK的动态代理和基于CGLIB(Code Generation Library)的动态代理。

    1. 基于JDK的动态代理:JDK动态代理是通过接口来实现的代理。它要求目标类必须实现接口,并且代理类与目标类实现相同的接口。JDK动态代理利用了Java的反射机制,在运行时创建一个实现了目标接口的代理对象。当调用代理对象的方法时,实际上是调用了代理类中的invoke方法。在invoke方法中,可以通过Method对象获取到被代理方法的信息,然后根据需要执行一些额外的逻辑。

    2. 基于CGLIB的动态代理:CGLIB是一个开源的代码生成库,可以在运行时生成Java类的字节码并动态加载到JVM中。CGLIB动态代理不需要目标类实现接口,而是通过继承目标类来创建代理对象。CGLIB动态代理通过Enhancer类和MethodInterceptor接口实现。Enhancer类负责生成代理类的字节码,而MethodInterceptor接口负责拦截方法调用并执行额外的逻辑。

    3. 动态代理的使用场景:动态代理可以用于实现AOP(面向切面编程)。通过使用动态代理,可以将一些通用的行为,如日志记录、事务管理等,从目标类中解耦出来,并在运行时动态地将其插入到目标方法的前后。这样可以提高代码的重用性和可维护性。

    4. JDK动态代理与CGLIB动态代理的选择:如果目标类实现了接口,那么通常使用JDK动态代理。因为使用JDK动态代理要求代理类和目标类实现相同的接口,所以只能代理接口定义的方法。而CGLIB动态代理可以代理任意的类和方法,包括final类和final方法。但是CGLIB动态代理使用了字节码生成技术,所以相对于JDK动态代理来说,会稍微耗费更多的资源。

    5. 使用Spring的AOP支持:Spring框架为动态代理提供了完整的支持。通过配置文件或注解,可以将切面逻辑与目标类进行绑定,从而实现AOP功能。Spring AOP底层使用了动态代理来生成代理对象,并在方法调用前后执行切面逻辑。这样,我们可以将一些通用的行为,如事务管理、异常处理等,从业务逻辑中分离出来,提高代码的可读性和可维护性。

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

    Spring框架中的动态代理是通过使用Java的反射机制和Java动态代理机制实现的。Spring框架提供了两种动态代理的方式:JDK动态代理和CGLIB动态代理。

    1. JDK动态代理:
      JDK动态代理是基于接口的代理,它要求被代理对象必须实现一个接口。JDK动态代理使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。

    实现步骤如下:

    1. 创建一个实现InvocationHandler接口的代理处理类,重写invoke方法,在invoke方法中进行代理逻辑的编写。
    2. 使用Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法创建代理对象,其中loader参数是类加载器,interfaces参数是被代理对象实现的接口,h参数是代理处理器对象。
    3. 通过代理对象调用方法时,实际上会调用代理处理器的invoke方法,根据方法名和参数进行相应的处理。

    示例代码如下:

    public interface Foo {
        void bar();
    }
    
    public class FooProxy implements InvocationHandler {
        private Object target;
    
        public FooProxy(Object target) {
            this.target = target;
        }
    
        @Override
        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;
        }
    
        public static void main(String[] args) {
            Foo foo = new FooImpl();
            FooProxy proxy = new FooProxy(foo);
    
            Foo proxyObj = (Foo) Proxy.newProxyInstance(FooProxy.class.getClassLoader(), new Class[]{Foo.class}, proxy);
    
            proxyObj.bar();
        }
    }
    
    1. CGLIB动态代理:
      CGLIB动态代理是基于继承的代理,它不要求被代理对象实现接口。CGLIB动态代理使用net.sf.cglib.proxy.Enhancer类来生成代理类。

    实现步骤如下:

    1. 创建一个实现MethodInterceptor接口的代理处理类,重写intercept方法,在intercept方法中进行代理逻辑的编写。
    2. 使用Enhancer.create(Class superClass, Callback callback)方法创建代理对象,其中superClass参数是被代理对象的类,callback参数是代理处理器对象。
    3. 通过代理对象调用方法时,实际上会调用代理处理器的intercept方法,根据方法名和参数进行相应的处理。

    示例代码如下:

    public class Foo {
        public void bar() {
            System.out.println("Foo bar");
        }
    }
    
    public class FooProxy implements MethodInterceptor {
        @Override
        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;
        }
    
        public static void main(String[] args) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(Foo.class);
            enhancer.setCallback(new FooProxy());
    
            Foo proxyObj = (Foo) enhancer.create();
    
            proxyObj.bar();
        }
    }
    

    总结:
    Spring框架的动态代理机制通过使用Java的反射和动态代理机制,可以在运行时动态地生成代理类,并在代理过程中进行一些额外的操作。 JDK动态代理适用于接口代理,CGLIB动态代理适用于类代理。开发者可以根据具体的需求选择合适的动态代理方式。

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

400-800-1024

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

分享本页
返回顶部