静态代理,jdk动态代理,cglib动态代理

本文介绍了静态代理在MyBatis中的应用,以及动态代理(JDK动态代理和CGLIB)的概念、原理和使用场景,包括JDK动态代理的`InvocationHandler`接口和CGLIB通过继承方式实现代理。
摘要由CSDN通过智能技术生成

代理模式就是用代理对象代替真实对象去完成相应的操作,并且能够在操作执行的前后对操作进行增强处理。

静态代理

mybatis使用的就是静态代理,相比动态代理,静态代理在编译期间就确定了代理类,因此在运行时的性能通常会比动态代理更好。
步骤:定义接口,真实类实现接口,代理类也实现接口

真实场景,我们现在有一个歌手,歌手只想唱歌,不想管其他的事情,这时歌手就需要一个代理人,歌手代理人完成除唱歌之外的所有琐事,等完成了一系列工作后,再让歌手来唱歌。

定义业务接口

public interface Service {
    void sing();
}

真实类实现业务接口

public class Singer implements Service{

    public void sing() {
        System.out.println("歌手演唱");
    }
}

代理人实现业务接口

public class SingerProxy implements Service{

    public void sing() {
        System.out.println("歌手经纪人预定唱歌时间");
        System.out.println("歌手经纪人预定唱歌场地");
        System.out.println("歌手经纪人通知歌手唱歌");
        Singer singer = new Singer();
        singer.sing();
        System.out.println("歌手经纪人清理场地");
    }
}

调用代理人去让歌手完成唱歌

public class Main {
    public static void main(String[] args) {
        SingerProxy singerProxy = new SingerProxy();
        singerProxy.sing();
    }

}

运行结果:
在这里插入图片描述

动态代理

静态代理的缺陷显而易见,每有一个真实类,我们就需要手动创建他的代理类,代码量巨大,这时我们的需求就是能不能动态生成。
动态代理是在程序运行时动态生成代理对象,而不是在编译时就确定代理对象。这意味着可以根据需要在运行时创建不同的代理对象,以满足不同的需求。

jdk动态代理

java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:

业务接口

public interface Service {
    void sing();
    void dance();
}

真实类实现业务接口

public class Singer implements Service{

    public void sing() {
        System.out.println("歌手演唱");
    }
    public void dance() {
        System.out.println("歌手跳舞");
    }

}

生成代理类

public class Main {
    public static void main(String[] args) {

        //创建真实对象
        Singer singer = new Singer();
        //动态创建真实对象的被代理对象
        Service proxy = createProxy(singer);

        proxy.sing();
    }

//生成代理类
    public static Service createProxy(Singer singer){

        Service proxy = (Service)Proxy.newProxyInstance(
                Singer.class.getClassLoader(),    //类的加载器
                new Class[]{Service.class},	    //接口数组
                new InvocationHandler() {       //调用处理器
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {				
                    	//proxy 代理对象,method正在执行的方法,agrs方法参数
                        //先获取正在执行的方法名
                        String name = method.getName();
                        Object result = null;
                        //
                        if ("sing".equals(name)) {
                            System.out.println("歌手经纪人预定唱歌时间");
                            System.out.println("歌手经纪人预定唱歌场地");
                            System.out.println("歌手经纪人通知歌手唱歌");
                            result = method.invoke(singer, args);
                            System.out.println("歌手经纪人清理场地");
                        }
                        if ("dance".equals(name)) {
                            System.out.println("歌手经纪人预定跳舞时间");
                            System.out.println("歌手经纪人预定跳舞场地");
                            System.out.println("歌手经纪人通知歌手唱跳");
                            result = method.invoke(singer, args);
                            System.out.println("歌手经纪人清理场地");
                        }
                        return result;
                    }
                });

        return proxy;
    }

}

JDK生成的动态代理类大概源码

动态生成的代理类其方法与实现的接口有关,接口有什么方法,他就实现什么方法。

当我们代理类对象.sing()时,代理类内部会有sing方法,sing方法中会super.h.invoke(代理对象本身,正在执行的方法,方法参数)。super是其父类Proxy,h是父类的属性InvocationHandler h,这个调用处理器是我们传给父类对象的。
当我们代理类对象.dance()时,代理类内部会有dance方法,dance方法同样有super.h.invoke(代理对象本身,正在执行的方法,方法参数)。super是其父类Proxy,h是父类的属性InvocationHandler h,这个调用处理器是我们传给父类对象的。

public final class $Proxy0 extends Proxy implements Service {
    private static Method m0;
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m4;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m0, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

	 public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m1, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
	
	public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

	//Method m3中有sing方法的信息,调用父类Proxy的protected InvocationHandler h 的invoke方法
    public final void sing() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

  
	//Method m4中有dance方法的信息
    public final void dance() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

   

    static {
        try {
            m0 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m1 = Class.forName("java.lang.Object").getMethod("toString");
            m2 = Class.forName("java.lang.Object").getMethod("hashCode");
            m3 = Class.forName("Service").getMethod("sing");
            m4 = Class.forName("Service").getMethod("dance");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

cglib动态代理

jdk动态代理需要接口,许多场景是没有接口的,这个时候就需要cglib动态代理了,CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。

cglib代理最重要的是实现MethodInterceptor接口,实现他的intercept方法
jdk代理最重要的是实现 InvocationHandler接口,实现他的invoke方法

当我们代理类对象.sing() --> MethodInterceptor. intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) -->根据类名通过反射调用对应的方法

intercept方法的四个参数
Object o, 被代理对象
Method method, 正在执行的方法
Object[] objects, 方法参数
MethodProxy methodProxy 方法代理对象

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值