spring如何实现动态代理

fiy 其他 14

回复

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

    Spring框架提供了两种方式实现动态代理:JDK动态代理和CGLIB动态代理。

    1. JDK动态代理:
      JDK动态代理是基于接口的代理模式,要求被代理的类实现一个或多个接口。JDK动态代理通过反射机制在运行时创建代理对象,可以动态地将方法调用转发到被代理对象上。

    首先,定义一个InvocationHandler接口的实现类,该类用于定义代理类的方法调用处理逻辑。在该类的invoke方法中,可以对方法进行增强、过滤或转发。

    然后,在服务类中调用Proxy.newProxyInstance方法创建代理对象。该方法接受三个参数:类加载器、被代理类实现的接口列表和InvocationHandler实例。

    最后,通过代理对象调用方法时,会自动执行代理逻辑。

    1. CGLIB动态代理:
      CGLIB动态代理是基于继承的代理模式,不要求被代理的类实现接口。CGLIB动态代理通过创建目标类的子类来实现代理。

    首先,引入CGLIB相关的依赖。然后定义一个方法拦截器类,该类用于定义代理类的方法调用处理逻辑。

    接着,使用Enhancer类创建代理对象。该类通过设置父类、方法拦截器和回调类型来创建代理对象。

    最后,通过代理对象调用方法时,会自动执行代理逻辑。

    总结:
    JDK动态代理适用于要求被代理类实现接口的场景,而CGLIB动态代理适用于不要求被代理类实现接口的场景。在Spring中,通过配置文件或注解即可使用这两种动态代理方式。

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

    Spring框架提供了两种实现动态代理的方式:JDK动态代理和CGLib动态代理。接下来将分别介绍这两种方式的实现方法。

    1. JDK动态代理
      JDK动态代理是基于接口的代理,它通过在运行时创建一个实现指定接口的代理类来实现代理功能。JDK动态代理的核心类是java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler。具体步骤如下:
    • 创建一个InvocationHandler实现类,重写invoke方法,在invoke方法中通过反射调用目标对象的方法。
    • 使用Proxy的静态方法newProxyInstance()创建代理对象,参数包括ClassLoader、代理接口数组和InvocationHandler。
    • 通过代理对象调用目标方法。
    1. CGLib动态代理
      CGLib动态代理是基于字节码的代理,它通过继承目标类来实现代理功能。CGLib动态代理的核心类是net.sf.cglib.proxy.Enhancer。具体步骤如下:
    • 创建一个MethodInterceptor实现类,重写intercept方法,在intercept方法中通过cglib库中的MethodProxy类调用目标对象的方法。
    • 使用Enhancer的create()方法创建代理对象,参数包括目标类和MethodInterceptor。
    • 通过代理对象调用目标方法。
    1. 配置动态代理
      无论是使用JDK动态代理还是CGLib动态代理,都需要将代理对象配置到Spring的配置文件中。在Spring配置文件中,需要指定目标对象和代理对象的关系,以及代理方式是JDK动态代理还是CGLib动态代理。

    2. 使用动态代理
      配置完成后,就可以在代码中使用动态代理了。可以通过注入代理对象来调用目标对象的方法,并在方法调用前后进行增强操作。

    3. 动态代理的应用场景
      动态代理在Spring框架中有着广泛的应用。它可以用来实现事务管理、日志记录、性能监控等功能。通过动态代理,可以将这些横切关注点与业务逻辑解耦,使得代码更加清晰和易于维护。

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

    Spring框架通过使用动态代理技术来实现许多功能,包括事务管理、AOP(面向切面编程)和远程方法调用等。Spring提供了两种主要的动态代理技术:JDK动态代理和CGLIB动态代理。

    1. JDK动态代理

    JDK动态代理基于Java的反射机制,只能对接口进行代理。JDK动态代理是通过接口的实例来生成代理对象,并且代理对象实现了接口中定义的方法。具体步骤如下:

    • 创建一个InvocationHandler接口的实现类,该类负责实现代理对象的具体操作逻辑。
    • 通过Proxy类的newProxyInstance方法创建代理对象。该方法接收三个参数:ClassLoader,用于指定代理对象的类加载器;Class[],用于指定代理对象实现的接口;InvocationHandler,用于指定代理对象的具体操作逻辑。
    • 使用代理对象进行方法调用。

    以下是一个示例代码:

    public interface UserDao {
        void save();
    }
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("Saving data...");
        }
    }
    
    public class MyInvocationHandler implements InvocationHandler {
        private Object target;
    
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Before method execution...");
            Object result = method.invoke(target, args);
            System.out.println("After method execution...");
            return result;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            UserDao userDao = new UserDaoImpl();
            InvocationHandler handler = new MyInvocationHandler(userDao);
            UserDao proxy = (UserDao) Proxy.newProxyInstance(
                    userDao.getClass().getClassLoader(),
                    userDao.getClass().getInterfaces(),
                    handler
                );
            proxy.save();
        }
    }
    

    代理对象执行save()方法时,会先执行MyInvocationHandler类中的invoke()方法,并在调用目标方法前后输出日志。

    1. CGLIB动态代理

    CGLIB动态代理是基于字节码生成技术实现的,可以对类进行代理。CGLIB会继承目标类,并重写其方法来实现代理。具体步骤如下:

    • 引入CGLIB库到项目中。
    • 创建一个MethodInterceptor接口的实现类,该类负责实现代理对象的具体操作逻辑。
    • 创建Enhancer对象,并设置父类以及回调函数。
    • 使用代理对象进行方法调用。

    以下是一个示例代码:

    public class UserDao {
        public void save() {
            System.out.println("Saving data...");
        }
    }
    
    public class MyMethodInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("Before method execution...");
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("After method execution...");
            return result;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(UserDao.class);
            enhancer.setCallback(new MyMethodInterceptor());
            UserDao proxy = (UserDao) enhancer.create();
            proxy.save();
        }
    }
    

    代理对象执行save()方法时,会先执行MyMethodInterceptor类中的intercept()方法,并在调用目标方法前后输出日志。

    总结:

    Spring框架通过使用JDK动态代理和CGLIB动态代理技术来实现动态代理。JDK动态代理只能对接口进行代理,基于Java的反射机制实现;CGLIB动态代理可以对类进行代理,基于字节码生成技术实现。开发者可以选择适合自己需求的动态代理技术来实现各种功能。

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

400-800-1024

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

分享本页
返回顶部