spring两种代理方式

Spring 提供了两种主要的代理(proxy)方式,分别是基于JDK动态代理和基于CGLIB的代理。这两种代理方式各有其特点和适用场景。

 1. JDK动态代理

特点:
- 基于Java的接口(Interface)。
- 代理类必须实现一个或多个接口。
- 使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。

优点:
- 实现简单,性能较好。
- 生成的代理类是接口的实现类,遵循面向接口编程的原则。

缺点:
- 只能代理接口,无法代理具体类。

适用场景:
- 被代理对象有一个或多个接口时。

代码示例:

java
public interface Service {
    void perform();
}

public class ServiceImpl implements Service {
    @Override
    public void perform() {
        System.out.println("Performing service...");
    }
}

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ServiceInvocationHandler implements InvocationHandler {
    private final Object target;

    public ServiceInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method invocation");
        Object result = method.invoke(target, args);
        System.out.println("After method invocation");
        return result;
    }

    public static void main(String[] args) {
        ServiceImpl service = new ServiceImpl();
        Service proxy = (Service) Proxy.newProxyInstance(
                service.getClass().getClassLoader(),
                new Class[]{Service.class},
                new ServiceInvocationHandler(service)
        );
        proxy.perform();
    }
}


 2. CGLIB代理

特点:
- 基于字节码生成,使用底层字节码增强技术。
- 可以代理没有实现接口的具体类。
- 使用net.sf.cglib.proxy.Enhancer类和net.sf.cglib.proxy.MethodInterceptor接口来实现。

优点:
- 可以代理具体类,不需要依赖接口。
- 能够代理方法调用,提高灵活性。

缺点:
- 性能比JDK动态代理稍差。
- 生成的代理类是目标类的子类,可能会有一些不兼容的情况(例如目标类是final类,或者目标方法是final方法时无法代理)。

适用场景:
- 被代理对象没有接口,或者需要代理类中的具体方法时。

代码示例:

java
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class Service {
    public void perform() {
        System.out.println("Performing service...");
    }
}

public class ServiceMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method invocation");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method invocation");
        return result;
    }

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Service.class);
        enhancer.setCallback(new ServiceMethodInterceptor());
        Service proxy = (Service) enhancer.create();
        proxy.perform();
    }
}


 总结

- 使用JDK动态代理时,必须有接口,适用于面向接口编程的场景。
- 使用CGLIB代理时,不需要接口,适用于需要代理具体类的方法的场景。
- Spring AOP默认使用JDK动态代理,如果没有接口才使用CGLIB代理。可以通过配置明确指定代理方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值