spring中aop使用什么代理

worktile 其他 31

回复

共3条回复 我来回复
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    Spring中AOP使用的是JDK动态代理和CGLIB代理两种方式。

    1. JDK动态代理:
      JDK动态代理是通过Java的反射机制来实现的,要求目标对象必须实现一个接口。在Spring中,通过配置一个实现了InvocationHandler接口的代理对象来实现AOP功能。当目标对象的方法被调用时,代理对象会通过反射调用InvocationHandler的invoke方法,在该方法中可以实现对目标对象方法的增强逻辑。

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

    1. 定义一个实现InvocationHandler接口的代理类;
    2. 创建目标对象的实例;
    3. 使用Proxy类的newProxyInstance方法创建代理对象;
    4. 调用代理对象的方法。

    JDK动态代理的优点是可以在运行时动态地创建代理对象,无需修改目标对象的源代码,缺点是只能代理实现了接口的目标对象。

    1. CGLIB代理:
      CGLIB是一个强大的基于字节码的动态代理库,它可以在运行时动态生成目标类的子类,从而实现代理的功能。相比于JDK动态代理,CGLIB代理不要求目标对象实现接口,可以代理目标对象的所有方法。

    使用CGLIB代理的步骤如下:

    1. 引入CGLIB的依赖;
    2. 定义一个实现MethodInterceptor接口的代理类;
    3. 创建Enhancer对象,设置父类和拦截器;
    4. 调用Enhancer对象的create方法创建代理对象;
    5. 调用代理对象的方法。

    CGLIB代理的优点是可以代理非接口的目标对象,缺点是生成代理类的过程比较耗时,会影响应用的启动速度。

    总结来说,Spring中AOP使用的是JDK动态代理和CGLIB代理两种方式,其中JDK动态代理适用于代理实现了接口的目标对象,而CGLIB代理适用于代理非接口的目标对象。

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

    在Spring中,AOP使用两种类型的代理:基于JDK的动态代理和基于CGLlib的动态代理。

    1. JDK动态代理:
      JDK动态代理是基于接口的代理。当目标对象实现了接口时,Spring将使用JDK动态代理生成目标对象的代理类。JDK动态代理是基于Java反射机制实现的。它利用了Java的动态代理API来创建代理对象。JDK动态代理使用的接口是java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy。

    2. CGLib动态代理:
      CGLib动态代理是基于继承的代理。CGLib通过生成目标对象的子类来创建代理对象,从而达到代理的目的。CGLib不需要目标对象实现接口,因此可以代理那些没有实现接口的目标对象。CGLib动态代理使用的类是net.sf.cglib.proxy.MethodInterceptor和net.sf.cglib.proxy.Enhancer。

    3. JDK动态代理和CGLib动态代理的区别:
      JDK动态代理可以代理实现了接口的类,而CGLib动态代理可以代理任意的类,包括没有实现接口的类。另外,JDK动态代理是基于接口的,所以目标对象必须实现接口;而CGLib动态代理是基于继承的,所以目标对象不需要实现接口。

    4. 如何选择代理方式:
      一般情况下,如果目标对象实现了接口,推荐使用JDK动态代理;如果目标对象没有实现接口,或者需要代理的是一个类而不是一个接口,可以使用CGLib动态代理。当然,Spring会根据情况自动选择合适的代理方式。

    5. 动态代理的应用场景:
      动态代理通常用于实现方法的增强。在Spring中,AOP就是通过动态代理实现的。动态代理可以在目标方法执行前后、异常时等切入额外的逻辑,比如日志记录、事务管理等。动态代理还常常用于实现代理工厂、缓存代理等功能。

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

    在Spring AOP中,使用了两种代理来实现AOP的功能:JDK动态代理和CGLIB代理。下面将详细介绍这两种代理的使用方法和实现原理。

    JDK动态代理:
    JDK动态代理是基于接口的代理,它的核心是Java提供的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。JDK动态代理只能对实现了接口的类生成代理,原理是通过在运行时生成一个代理类,该代理类通过实现目标对象的接口,并将方法的调用委托给InvocationHandler来处理。

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

    1. 定义一个InvocationHandler。
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    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 call");
            Object result = method.invoke(target, args); // 调用目标对象的方法
            // 在代理对象调用方法后可以添加一些逻辑
            System.out.println("After method call");
            return result;
        }
    }
    
    1. 创建代理对象。
    import java.lang.reflect.Proxy;
    
    public class ProxyFactory {
        public static Object getProxy(Object target) {
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new MyInvocationHandler(target));
        }
    }
    

    其中,Proxy.newProxyInstance()方法用于创建代理对象,它接受三个参数:ClassLoader,目标对象实现的接口数组,和InvocationHandler对象。

    1. 使用代理对象调用方法。
    public interface UserService {
        void addUser(String username, String password);
    }
    
    public class UserServiceImpl implements UserService {
        @Override
        public void addUser(String username, String password) {
            System.out.println("Add user: " + username);
        }
    }
    
    public class Main() {
        public static void main(String[] args) {
            UserService userService = new UserServiceImpl();
            UserService proxy = (UserService) ProxyFactory.getProxy(userService);
            proxy.addUser("John", "123456");
        }
    }
    

    输出结果:

    Before method call
    Add user: John
    After method call
    

    CGLIB代理:
    CGLIB代理是基于继承的代理,它不要求目标对象实现接口,原理是通过继承目标对象,并使用Enhancer类生成目标对象的子类,子类中增加了增强的代码。

    使用CGLIB代理的步骤如下:

    1. 添加CGLIB的依赖。
      在Maven项目中,需要添加以下依赖:
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>
    
    1. 定义一个MethodInterceptor。
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class MyMethodInterceptor 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;
        }
    }
    
    1. 创建代理对象。
    import net.sf.cglib.proxy.Enhancer;
    
    public class ProxyFactory {
        public static Object getProxy(Object target) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass()); // 设置父类,即目标对象的类
            enhancer.setCallback(new MyMethodInterceptor()); // 设置回调对象
            return enhancer.create();
        }
    }
    
    1. 使用代理对象调用方法。
    public class UserService {
        public void addUser(String username, String password) {
            System.out.println("Add user: " + username);
        }
    }
    
    public class Main() {
        public static void main(String[] args) {
            UserService userService = new UserService();
            UserService proxy = (UserService) ProxyFactory.getProxy(userService);
            proxy.addUser("John", "123456");
        }
    }
    

    输出结果:

    Before method call
    Add user: John
    After method call
    

    综上所述,Spring AOP使用JDK动态代理和CGLIB代理来实现AOP的功能。JDK动态代理适用于接口代理,CGLIB代理适用于类代理。在选择代理时,需要根据目标对象是否实现接口来决定使用哪种代理;同时,CGLIB代理由于是基于继承的代理,可能会对final类和final方法无效。

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

400-800-1024

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

分享本页
返回顶部