关于spring代理模式详细说明

spring代理模式分为动态代理和静态代理。
动态代理又分为JDK动态代理和CGLIB动态代理。

1、静态代理

首先,先定义一个公共接口Subject:

public interface Subject {
    void request();
}

然后,定义一个具体主题类RealSubject,实现Subject接口:

public class RealSubject implements Subject {
    public void request() {
        System.out.println("RealSubject's request() method is called.");
    }
}

接下来是静态代理的实现:

public class ProxySubject implements Subject {
    private RealSubject realSubject;

    public ProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    public void request() {
        System.out.println("Before RealSubject's request() method is called.");
        realSubject.request();
        System.out.println("After RealSubject's request() method is called.");
    }

    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        ProxySubject proxySubject = new ProxySubject(realSubject);
        proxySubject.request();
    }
}

可以看到,代理类ProxySubject实现了Subject接口,并在构造方法中接受一个RealSubject对象,然后在代理方法request中调用RealSubject的方法,并在方法执行前后加入了额外的逻辑。

最后,在main方法中,创建了RealSubject对象和ProxySubject对象,通过调用ProxySubject的request方法实现了对RealSubject对象的代理调用。

静态代理的优点在于实现简单、易于理解,并且可以在编译期间就生成代理类,运行效率高。缺点在于当需要代理的接口或类过多时,需要手动编写大量的代理类,工作量较大。

2、JDK动态代理

DK动态代理是Java动态代理的默认实现,它通过java.lang.reflect.Proxy类来实现。JDK动态代理要求目标类必须实现一个或多个接口,代理类实现目标类实现的所有接口,并在代理类的方法中调用目标对象的方法。

DK动态代理的优点在于可以代理接口,实现接口之间的代理,同时不需要额外的依赖,可以在运行时实现动态代理。缺点是只能代理实现了接口的类,不能代理没有实现接口的类。

下面是一个简单的示例:

public interface Subject {
    void request();
}

public class RealSubject implements Subject {
    public void request() {
        System.out.println("RealSubject's request() method is called.");
    }
}

public class ProxySubject implements InvocationHandler {
    private Object target;

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

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

    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        ProxySubject proxySubject = new ProxySubject(realSubject);
        Subject subject = (Subject)Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), proxySubject);
        subject.request();
    }
}

3、CGLIB动态代理

CGLIB(Code Generation Library)动态代理是一种基于ASM(Java字节码操纵框架)开发的动态代理技术。CGLIB动态代理是在运行期间动态生成代理类,通过继承目标类并重载目标方法的方式实现代理,可以代理没有实现接口的类。

CGLIB动态代理的优点在于可以代理没有实现接口的类,灵活度更高,同时它的速度比JDK动态代理要快一些。缺点是它是基于继承实现的,如果目标对象中存在final类或方法,则无法代理。

下面是一个简单的示例:

public class RealSubject {
    public void request() {
        System.out.println("RealSubject's request() method is called.");
    }
}

public class ProxySubject implements MethodInterceptor {
    private RealSubject target;

    public ProxySubject(RealSubject target) {
        this.target = target;
    }

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before " + method.getName() + " is called.");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After " + method.getName() + " is called.");
        return result;
    }

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new ProxySubject(new RealSubject()));
        RealSubject subject = (RealSubject) enhancer.create();
        subject.request();
    }
}

在以上示例中,我们定义了一个RealSubject类和一个ProxySubject类,RealSubject类并没有实现任何接口,ProxySubject类在构造方法中接受一个RealSubject对象,并实现了MethodInterceptor接口,通过设置CGLIB Enhancer类的Superclass和Callback属性,可以生成代理类并实现对目标对象的代理调用。

综上,JDK动态代理和CGLIB动态代理各有优缺点,使用场景和方式不同,需要根据具体的情况选择合适的方式来实现动态代理。在Spring AOP中,通常采用JDK动态代理执行接口代理和CGLIB动态代理执行类代理。

JDK动态代理和CGLIB动态代理区别

1、实现方式

JDK动态代理是基于接口实现的代理,它要求目标类必须实现至少一个接口,然后通过Java反射机制在运行时生成动态代理类,代理类实现了目标类实现的所有接口,并在代理类的方法中调用目标对象的方法。

CGLIB动态代理则是基于继承实现的代理,它不要求目标类必须实现接口,而是通过ASM字节码处理框架直接对目标类的字节码进行修改,生成一个目标类的子类,代理类继承自目标类的子类,并重写目标类的方法,在重写的方法中调用目标对象的方法。
因此,JDK动态代理只能代理实现了接口的类,而CGLIB动态代理可以代理没有实现接口的类。

2、使用场景

JDK动态代理由于要实现接口,只能代理某些具有共同接口的类,对于没有实现接口的类,它则无法完成对这些类的代理,所以JDK动态代理在实际开发中的使用场景比CGLIB动态代理更加局限。

CGLIB动态代理则在无法使用JDK动态代理的场合下发挥着重要的作用。比如,当目标类没有实现接口或者只想代理目标类的某一个方法时,就可以使用CGLIB动态代理。

3、性能

JDK动态代理的实现是基于Java反射机制的动态代理,所以在创建代理对象的时候,会耗费比较长的时间来做类型检查、安全检查等操作,相对比较慢。

CGLIB动态代理采用ASM字节码框架,并通过在运行时动态生成字节码,比较快。但是,由于CGLIB动态代理是基于继承实现的,所以对目标类中使用final关键字修饰的方法则无法对其进行代理。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一叶飘零晋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值