设计模式——代理模式

代理模式

​        代理模式在 Java 开发中是⼀种⽐较常⻅的设计模式。设计⽬的旨在为服务类与客户类之间插⼊其他
功能,插⼊的功能对于调⽤者是透明的,起到伪装控制的作⽤。如租房的例⼦:房客、中介、房东。对
应于代理模式中即:客户类、代理类 、委托类(被代理类)。

​        为某⼀个对象(委托类)提供⼀个代理(代理类),⽤来控制对这个对象的访问。委托类和代理类有
⼀个共同的⽗类或⽗接⼝。代理类会对请求做预处理、过滤,将请求分配给指定对象。

代理的三要素

​ a、有共同的⾏为(结婚) - 接⼝
​ b、⽬标⻆⾊(新⼈) - 实现⾏为
​ c、代理⻆⾊(婚庆公司) - 实现⾏为 增强⽬标对象⾏为

静态代理

​ 静态代理的特点
​ 1、⽬标⻆⾊固定
​ 2、在应⽤程序执⾏前就得到⽬标⻆⾊
​ 3、代理对象会增强⽬标对象的⾏为
​ 4、有可能存在多个代理 引起"类爆炸"(缺点)



动态代理

​        相⽐于静态代理,动态代理在创建代理对象上更加的灵活,动态代理类的字节码在程序运⾏时,由
Java反射机制动态产⽣。它会根据需要,通过反射机制在程序运⾏期,动态的为⽬标对象创建代理对
象,⽆需程序员⼿动编写它的源代码。动态代理不仅简化了编程⼯作,⽽且提⾼了软件系统的可扩展
性,因为反射机制可以⽣成任意类型的动态代理类。代理的⾏为可以代理多个⽅法,即满⾜⽣产需要的
同时⼜达到代码通⽤的⽬的。

动态代理的两种实现方式:

  1. JDK 动态代理
  2. CGLIB动态代理

动态代理的特点

  1. ⽬标对象不固定

  2. 在应⽤程序执⾏时动态创建⽬标对象

  3. 代理对象会增强⽬标对象的⾏为



JDK动态代理

注:JDK动态代理的⽬标对象必须有接⼝实现

获取代理对象

public class JdkProxy {

    /*
    	获取代理对象
    */
    public static Object getJdkProxy(Object object){
        Class clazz = object.getClass();
		//1、调⽤⽬标对象的⽅法(返回Object)
		//2、增强⽬标对象的⾏为
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                Object invoke = method.invoke(object, args);
                System.out.println("没有闪");
                return invoke;
            }
        });

    }
}

Java动态代理类中的invoke是怎么调⽤的?
	       在⽣成的动态代理类$Proxy0.class中,构造⽅法调⽤了⽗类Proxy.class的构造⽅法,给成员变
量invocationHandler赋值,$Proxy0.classstatic模块中创建了被代理类的⽅法,调⽤相应⽅法时⽅法体中调⽤了⽗类中的成员变量InvocationHandler的invoke()⽅法。



CGLIB 动态代理

       JDK的动态代理机制只能代理实现了接⼝的类,⽽不能实现接⼝的类就不能使⽤JDK的动态代理,
cglib是针对类来实现代理的,它的原理是对指定的⽬标类⽣成⼀个⼦类,并覆盖其中⽅法实现增强,但
因为采⽤的是继承,所以不能对final修饰的类进⾏代理。

添加依赖
在pom.xml⽂件中引⼊cglib的相关依赖

<dependency>
	<groupId>cglib</groupId>
	<artifactId>cglib</artifactId>
	<version>2.2.2</version>
</dependency>

创建代理对象

public class CglibProxy {
    public static Object getProxy(Object obj){
        // 通过Enhancer对象的create()⽅法可以⽣成⼀个类,⽤于⽣成代理对象
        Enhancer enhancer = new Enhancer();
        // 设置⽗类 (将⽬标类作为其⽗类)
        enhancer.setSuperclass(obj.getClass());
        // 设置拦截器 回调对象为本身对象
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object invoke = method.invoke(obj, objects);
                System.out.println("没有闪");
                return invoke;
            }
        });
        // ⽣成⼀个代理类对象,并返回
        return enhancer.create();

    }
}

JDK代理与CGLIB代理的区别

  • JDK动态代理实现接⼝,Cglib动态代理继承思想
  • JDK动态代理(⽬标对象存在接⼝时)执⾏效率⾼于Ciglib
  • 如果⽬标对象有接⼝实现,选择JDK代理,如果没有接⼝实现选择Cglib代理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值