spring怎么代理动态

worktile 其他 24

回复

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

    Spring提供了多种方式来实现动态代理。

    一、JDK动态代理
    JDK动态代理是通过反射机制来实现的,它要求目标类实现接口。

    1. 创建目标类接口:
    public interface TargetInterface {
        void doSomething();
    }
    
    1. 创建目标类:
    public class Target implements TargetInterface {
        @Override
        public void doSomething() {
            System.out.println("目标类方法执行");
        }
    }
    
    1. 创建代理类:
    public class TargetProxy implements InvocationHandler {
        private Object target;
    
        public Object bind(Object target) {
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("代理前操作");
            Object result = method.invoke(target, args);
            System.out.println("代理后操作");
            return result;
        }
    }
    
    1. 使用代理类:
    public class Main {
        public static void main(String[] args) {
            Target target = new Target();
            TargetProxy targetProxy = new TargetProxy();
            TargetInterface proxy = (TargetInterface) targetProxy.bind(target);
            proxy.doSomething();
        }
    }
    

    运行结果:

    代理前操作
    目标类方法执行
    代理后操作
    

    二、CGLIB动态代理
    CGLIB动态代理是通过生成子类来实现的,它不要求目标类实现接口。

    1. 创建目标类:
    public class Target {
        public void doSomething() {
            System.out.println("目标类方法执行");
        }
    }
    
    1. 创建代理类:
    public class TargetProxy implements MethodInterceptor {
        public Object bind(Class targetCls) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(targetCls);
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("代理前操作");
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("代理后操作");
            return result;
        }
    }
    
    1. 使用代理类:
    public class Main {
        public static void main(String[] args) {
            Target target = new Target();
            TargetProxy targetProxy = new TargetProxy();
            Target proxy = (Target) targetProxy.bind(Target.class);
            proxy.doSomething();
        }
    }
    

    运行结果:

    代理前操作
    目标类方法执行
    代理后操作
    

    总结:
    JDK动态代理要求目标类实现接口,适用于对接口进行代理;CGLIB动态代理不要求目标类实现接口,适用于对类进行代理。根据需求选择不同的动态代理方式即可。

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

    在Spring中,代理是实现AOP(面向切面编程)的核心机制之一。通过代理,可以在不修改原有代码的情况下,向方法调用前后添加额外的处理逻辑。Spring提供了两种代理方式:基于接口的JDK动态代理和基于类的CGLIB动态代理。

    1. JDK动态代理:
      JDK动态代理是通过Java的反射机制来实现的,要求目标类必须实现一个或多个接口。Spring使用Proxy类和InvocationHandler接口来创建代理对象。具体步骤如下:
      (1)创建目标类的接口;
      (2)实现InvocationHandler接口,重写invoke方法,在invoke方法中添加额外的逻辑;
      (3)使用Proxy类的newProxyInstance方法创建代理对象,需要传入ClassLoader、目标类的接口数组和InvocationHandler对象;
      (4)通过代理对象调用目标方法。

    2. CGLIB动态代理:
      如果目标类没有实现接口,就无法使用JDK动态代理。这时可以使用CGLIB动态代理。CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,它可以在运行时生成代理类。Spring使用Enhancer类和MethodInterceptor接口来创建CGLIB代理对象。具体步骤如下:
      (1)创建目标类;
      (2)实现MethodInterceptor接口,重写intercept方法,在intercept方法中添加额外的逻辑;
      (3)创建Enhancer对象,设置目标类和MethodInterceptor对象,并设置Enhancer的父类为目标类;
      (4)通过Enhancer的create方法创建代理对象;
      (5)通过代理对象调用目标方法。

    3. 配置Spring AOP代理:
      使用Spring AOP代理的方式有两种:基于XML配置和基于注解配置。
      (1)基于XML配置:需要在Spring的配置文件中添加AOP的相关配置,包括代理方式、目标类、切点表达式和通知等;
      (2)基于注解配置:通过在类或方法上添加注解来指定代理方式、切点和通知等。

    4. 代理AspectJ切面:
      Spring AOP默认使用基于代理的AOP实现,但也支持使用AspectJ切面来实现AOP。AspectJ切面是使用AspectJ编译器进行编译的,能够在编译时织入切面代码,提供更强大的功能和性能。要使用AspectJ切面,需要引入相关的依赖,并在Spring配置文件中添加AspectJ的命名空间。

    5. 选择代理方式:
      选择使用JDK动态代理还是CGLIB动态代理,取决于目标类是否实现了接口。如果目标类实现了接口,优先考虑使用JDK动态代理;如果目标类没有实现接口,才考虑使用CGLIB动态代理。另外,性能方面,JDK动态代理效率较高,而CGLIB动态代理效率较低。因此,在性能要求较高的情况下,可以优先选择JDK动态代理。

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

    Spring提供了两种方式来实现动态代理:JDK动态代理和CGLIB代理。下面将分别介绍这两种代理方式的操作流程和方法。

    一、JDK动态代理
    JDK动态代理是一种基于接口的代理,只能为接口创建代理对象。操作流程如下:

    1. 定义接口:首先需要定义一个接口,用于描述被代理对象的行为。

    2. 实现目标对象:定义一个类,实现上一步定义的接口。

    3. 创建代理对象:使用Proxy类的newProxyInstance方法创建代理对象,该方法接受三个参数:ClassLoader对象、一个实现了InvocationHandler接口的对象和一个Class对象。

    4. 实现InvocationHandler接口:创建一个类,实现InvocationHandler接口,并根据业务逻辑编写invoke方法。

    下面是一个简单的示例代码:

    1. 定义接口:
    public interface HelloService {
        void sayHello(String name);
    }
    
    1. 实现目标对象:
    public class HelloServiceImpl implements HelloService {
        @Override
        public void sayHello(String name) {
            System.out.println("Hello, " + name);
        }
    }
    
    1. 创建代理对象:
    public class HelloServiceProxy implements InvocationHandler {
        private Object target; // 被代理的目标对象
    
        public HelloServiceProxy(Object target) {
            this.target = target;
        }
    
        public Object getProxy() {
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Before invoke method: " + method.getName());
            Object result = method.invoke(target, args);
            System.out.println("After invoke method: " + method.getName());
            return result;
        }
    }
    
    1. 测试代码:
    public class Main {
        public static void main(String[] args) {
            HelloService helloService = new HelloServiceImpl();
            HelloService proxy = (HelloService) new HelloServiceProxy(helloService).getProxy();
            proxy.sayHello("World");
        }
    }
    

    执行上述代码,输出结果为:

    Before invoke method: sayHello
    Hello, World
    After invoke method: sayHello
    

    二、CGLIB代理
    CGLIB代理是一种基于继承的代理,可以为任意类创建代理对象。操作流程如下:

    1. 导入CGLIB库:首先需要导入CGLIB的相关库。

    2. 创建Enhancer对象:使用Enhancer类的create方法创建Enhancer对象。

    3. 设置父类和回调:调用Enhancer对象的setSuperclass方法设置父类,并调用setCallback方法设置回调对象。

    4. 创建代理对象:使用Enhancer对象的create方法创建代理对象。

    下面是一个简单的示例代码:

    1. 添加CGLIB库:
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>
    
    1. 创建代理类:
    public class UserService {
        public void saveUser() {
            System.out.println("Save user");
        }
    }
    
    1. 创建代理对象:
    public class UserServiceProxy implements MethodInterceptor {
        // 创建代理对象
        public Object createProxy(Object target) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("Before invoke method: " + method.getName());
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("After invoke method: " + method.getName());
            return result;
        }
    }
    
    1. 测试代码:
    public class Main {
        public static void main(String[] args) {
            UserService userService = new UserService();
            UserService proxy = (UserService) new UserServiceProxy().createProxy(userService);
            proxy.saveUser();
        }
    }
    

    执行上述代码,输出结果为:

    Before invoke method: saveUser
    Save user
    After invoke method: saveUser
    

    总结:
    Spring提供了JDK动态代理和CGLIB代理两种方式来实现动态代理。JDK动态代理基于接口,只能为接口创建代理对象;CGLIB代理基于继承,可以为任意类创建代理对象。使用这两种代理方式可以实现在调用目标对象的方法前后进行一些额外的操作。

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

400-800-1024

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

分享本页
返回顶部