spring怎么实现动态代理

fiy 其他 37

回复

共3条回复 我来回复
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    Spring框架通过使用AOP(面向切面编程)技术来实现动态代理。动态代理是一种运行时生成代理对象的方式,它可以在不修改源代码的情况下增强现有类的功能。在Spring中,有两种常见的动态代理方式:JDK动态代理和CGLIB动态代理。

    1. JDK动态代理
      JDK动态代理只能代理接口,它基于Java的反射机制实现。以下是实现动态代理的步骤:

    (1)创建一个InvocationHandler接口的实现类,该类需要重写invoke方法,用于在代理对象方法调用前后执行自定义逻辑。

    (2)通过Proxy类的newProxyInstance方法创建代理对象,该方法接受三个参数:类加载器、代理接口数组和InvocationHandler实例。

    例如,假设需要代理一个UserService接口:

    public interface UserService {
        void addUser(String username);
        void deleteUser(String username);
    }
    
    public class UserServiceImpl implements UserService {
        public void addUser(String username) {
            System.out.println("添加用户:" + username);
        }
        public void deleteUser(String username) {
            System.out.println("删除用户:" + username);
        }
    }
    
    public 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: " + method.getName());
            Object result = method.invoke(target, args);
            System.out.println("After method: " + method.getName());
            return result;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            UserService userService = new UserServiceImpl();
            MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);
            UserService proxy = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(),
                    new Class<?>[]{UserService.class}, invocationHandler);
            proxy.addUser("Bob");
            proxy.deleteUser("Alice");
        }
    }
    
    1. CGLIB动态代理
      CGLIB动态代理可以代理类,它是基于字节码技术实现的。以下是实现动态代理的步骤:

    (1)添加CGLIB库依赖。

    (2)创建一个MethodInterceptor接口的实现类,该类需要重写intercept方法,用于在代理对象方法调用前后执行自定义逻辑。

    (3)通过Enhancer类的create方法创建代理对象,该方法接受三个参数:被代理类的类类型、MethodInterceptor实例和MethodProxy实例。

    例如,假设需要代理一个UserService类:

    public class UserService {
        public void addUser(String username) {
            System.out.println("添加用户:" + username);
        }
        public void deleteUser(String username) {
            System.out.println("删除用户:" + username);
        }
    }
    
    public class MyMethodInterceptor implements MethodInterceptor {
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("Before method: " + method.getName());
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("After method: " + method.getName());
            return result;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(UserService.class);
            enhancer.setCallback(new MyMethodInterceptor());
            UserService proxy = (UserService) enhancer.create();
            proxy.addUser("Bob");
            proxy.deleteUser("Alice");
        }
    }
    

    无论是JDK动态代理还是CGLIB动态代理,在Spring框架中都能够很方便地实现,通过配置相关的切面和代理类,Spring会在运行时自动生成代理对象,并根据配置的切面将代理逻辑织入到目标对象中。

    1年前 0条评论
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    Spring框架提供了多种实现动态代理的方式,以下是其中几种常用的方法:

    1. JDK动态代理:
      JDK动态代理是通过反射机制实现的。在运行时创建一个实现了给定接口的代理类,并在代理类的方法中调用InvocationHandler对象的invoke()方法来实现代理逻辑。使用JDK动态代理时,被代理的类必须实现至少一个接口。

    2. CGLIB动态代理:
      CGLIB动态代理是通过字节码生成库实现的,它通过继承目标对象来实现代理。CGLIB在运行时动态生成一个被代理类的子类,并重写目标类的方法来实现代理逻辑。与JDK动态代理不同,CGLIB动态代理可以代理没有实现接口的类。

    3. Spring AOP:
      Spring AOP是一种基于代理模式的AOP实现框架,在Spring中,可以通过配置文件或注解来简化动态代理的使用。通过在配置文件中声明切面、切点和通知,可以实现对目标方法的动态代理。Spring AOP默认使用JDK动态代理,但也可以配置为使用CGLIB动态代理。

    4. Annotation-driven代理:
      使用Spring的@Aspect注解和其他相关注解可以实现基于注解的代理。可以使用@Aspect注解声明切面并使用其他注解来定义切点和通知,以实现对目标方法的动态代理。该方法提供了一种更简洁、易于理解和维护的方式来实现动态代理。

    5. 编程式代理:
      在某些情况下,可能需要以编程方式手动创建动态代理对象。Spring框架提供了ProxyFactory类,可以用于手动创建动态代理对象,通过设置目标对象和通知对象,可以实现代理逻辑。

    总结:
    Spring框架提供了多种实现动态代理的方式,包括JDK动态代理、CGLIB动态代理、Spring AOP、Annotation-driven代理和编程式代理。开发人员可以根据具体需求选择合适的方法来实现动态代理。

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

    Spring提供了两种方式来实现动态代理:

    一、使用JDK动态代理
    JDK动态代理是通过Java原生的反射机制实现的,它要求目标类必须实现一个接口。下面是实现动态代理的步骤:

    1. 创建目标类和接口
      首先需要创建一个目标类和对应的接口,目标类实现了该接口。

    2. 创建代理类
      创建一个类实现InvocationHandler接口,并实现invoke方法。在invoke方法中可以对目标类进行前置和后置增强等操作。

    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: " + method.getName());
            
            // 调用目标方法
            Object result = method.invoke(target, args);
            
            // 后置增强
            System.out.println("After method: " + method.getName());
    
            return result;
        }
    }
    
    1. 使用Proxy类创建代理对象
      使用Proxy类的静态方法newProxyInstance()创建代理对象。该方法接收三个参数:ClassLoader,接口数组和InvocationHandler对象。
    public class Main {
        public static void main(String[] args) {
            // 创建目标对象
            UserService userService = new UserServiceImpl();
            
            // 创建代理对象
            UserService proxy = (UserService) Proxy.newProxyInstance(
                userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                new MyInvocationHandler(userService)
            );
            
            // 调用代理方法
            proxy.addUser("Alice");
        }
    }
    

    二、使用CGLIB动态代理
    CGLIB是一个强大的第三方类库,它通过创建目标类的子类来实现动态代理,无需目标类实现接口。

    1. 添加CGLIB依赖
      首先需要在项目中添加CGLIB的依赖,可以通过Maven或者Gradle进行添加。

    2. 创建目标类
      创建一个目标类,该类将作为代理对象进行使用。

    3. 创建代理类
      创建一个类继承MethodInterceptor接口,并实现intercept方法。在该方法中可以对目标类进行前置和后置增强等操作。

    public class MyMethodInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            // 前置增强
            System.out.println("Before method: " + method.getName());
            
            // 调用目标方法
            Object result = proxy.invokeSuper(obj, args);
            
            // 后置增强
            System.out.println("After method: " + method.getName());
    
            return result;
        }
    }
    
    1. 使用Enhancer创建代理对象
      使用Enhancer类的create()方法创建代理对象。该方法接收两个参数:目标类的Class对象和MethodInterceptor对象。
    public class Main {
        public static void main(String[] args) {
            // 创建目标对象
            UserService userService = new UserService();
            
            // 创建Enhancer对象
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(UserService.class);
            enhancer.setCallback(new MyMethodInterceptor());
            
            // 创建代理对象
            UserService proxy = (UserService) enhancer.create();
            
            // 调用代理方法
            proxy.addUser("Alice");
        }
    }
    

    注意事项:

    1. JDK动态代理要求目标类必须实现一个接口,而CGLIB动态代理则无此要求。
    2. JDK动态代理是基于接口的代理,而CGLIB动态代理是基于类的代理。
    3. JDK动态代理使用Java原生的反射机制,而CGLIB动态代理则使用了第三方类库。
    1年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

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

分享本页
返回顶部