3_代理模式(动态代理JDK原生和CGLib)

这篇具有很好参考价值的文章主要介绍了3_代理模式(动态代理JDK原生和CGLib)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.代理模式

1.概念

代理模式(Proxy Pattern )是指为其他对象提供一种代理,以控制对这个对象的访问,属于结构型模式。

在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象

2.代理模式三种角色

2.1 抽象角色( Subject ): 抽象主题类的主要职责是声明真实主题与代理的共同接口方法,该类可以是接口也可以是抽象类

2.2 真实角色(RealSubiect ): 该类也被称为被代理类,该类定义了代理所表示的真实对象,是负责执行系统真正的逻辑业务对象:

2.3 代理角色 ( Proxy): 也被称为代理类,其内部持有 RealSubiect 的用,因此具备完全的对RealSubiect 的代理权。客户端调用代理对象的方法,同时也调用被代理对象的方法,但是会在代理对象前后增加一些处理代码

二.代理模式的通用写法

2.1 创建一个抽象角色:用于代理和真实对象共同接口方法。

public interface ISubject {
    void request();
}

2.2 创建一个真实角色:用于执行真正的业务逻辑处理。

public class RealSubject implements ISubject {
    public void request() {
        System.out.println("real service is called.");
    }
}

2.3 创建一个代理角色:调用真实业务逻辑时候前后自己处理逻辑代码。

public class Proxy implements ISubject {
    //1.获取真实对象封装处理
    private ISubject subject;
    public Proxy(ISubject subject){
        this.subject = subject;
    }
    
    //2.调用真实对象业务逻辑,前后加一些自己逻辑增强处理。
    public void request() {
        before();
        subject.request();
        after();
    }
    
    //3.前后增加逻辑处理
    public void before(){
        System.out.println("called before request().");
    }
    public void after(){
        System.out.println("called after request().");
    }
}

2.4 测试功能

public class Client {
    public static void main(String[] args) {
        //创建代理对象并绑定一个真实对象
        Proxy proxy = new Proxy(new RealSubject());
        //执行代理对象功能调用
        proxy.request();
    }
}

//--结果处理------------
called before request().
real service is called.
called after request().

三.静态代理到动态代理

1.抽取角色:定义一个接口用于真实和代理对象共同的接口方法
//定义人的接口,相亲接口方法
public interface IPerson {
    void findLove();
}
2.真是角色:创建一个真正的人的对象并实现相亲接口方法具体逻辑
//定义一个张三人对象并提出相亲的要求
public class ZhangSan implements IPerson {
    public void findLove() {
        System.out.println("张三:要求相亲女孩长得好看又善良");
    }
}

3.代理角色:创建一个代理张三对象(张三的父亲)代理完成张三的相亲要求。
public class ZhangLaosan implements IPerson {
    //---静态代理------------------------
    //1.创建获取静态代理对象处理【只能接受张三这个人,其他人不能接受】
    private ZhangSan zhangsan;
    public ZhangLaosan(ZhangSan zhangsan) {
        this.zhangsan = zhangsan;
    }
    //2.完成张三的相亲,并在相亲的前后做一些工作和处理。
    public void findLove() {
        System.out.println("张老三开始物色");
        zhangsan.findLove();
        System.out.println("开始交往");
    }
    
    //---动态代理------------------------
    //1.创建获取动态代理对象处理【只要实现抽象角色的接口,任何真实对象都可以接受并执行代理逻辑】
    private IPerson person;
    public ZhangLaosan(IPerson person) {
        this.person = person;
    }
    //2.完成张三的相亲,并在相亲的前后做一些工作和处理。
    public void findLove() {
        System.out.println("张老三开始物色");
        person.findLove();
        System.out.println("开始交往");
    }
}

4.测试代码
public class Test {
    public static void main(String[] args) {
        ZhangLaosan zhangLaosan = new ZhangLaosan(new ZhangSan());
        zhangLaosan.findLove();
    }
}

结果:
 张老三开始物色
 张三:要求相亲女孩长得好看又善良
 开始交往

四. JDKProxy动态代理

1.抽取角色:定义一个接口用于真实和代理对象共同的接口方法
public interface IPerson {
    void findLove();
}

2.真是角色:创建一个真正的人的对象并实现相亲接口方法具体逻辑
//定义一个张三人对象并提出相亲的要求
public class ZhangSan implements IPerson {
    public void findLove() {
        System.out.println("张三:要求相亲女孩长得好看又善良");
    }
}

3.代理角色:创建一个代理张三对象(张三的父亲)代理完成张三的相亲要求。
public class JdkMeipo implements InvocationHandler {
    //1.定义接受真实对象变量
    private IPerson target;
    public IPerson getInstance(IPerson target){
        this.target = target; //真实对象赋值
        //clazz.getClassLoader():真实对象反射类对象(可以通过目标类的getClassLoader()方法来获取目标类的ClassLoader对象)
        //clazz.getInterfaces():真实对象接口列表 (Class[]对象,代理类要实现的接口列表。代理类将会实现这些接口,并且可以调用接口中定义的方法)
        //this:真实对象(InvocationHandler接口的实现类对象,代理类在调用方法时会委托给该InvocationHandler对象来处理)
        Class<?> clazz =  target.getClass();
        return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(this.target,args);
        after();
        return result;
    }

    private void after() {
        System.out.println("双方同意,开始交往");
    }
    private void before() {
        System.out.println("我是媒婆,已经收集到你的需求,开始物色");
    }
}

4.测试
public class Test {
    public static void main(String[] args) {
        JdkMeipo jdkMeipo = new JdkMeipo();//创建一个代理对象
        IPerson zhangsan = jdkMeipo.getInstance(new Zhangsan());//把真实对象代理处理一个代理张三的对象
        zhangsan.findLove();
    }
}

结果:
 张老三开始物色
 张三:要求相亲女孩长得好看又善良
 开始交往

五. CGlib动态代理

依赖maven cglib库

cglib
cglib-nodep
2.2

1.定义真实对象类并写真实的业务逻辑处理。
public class Customer {
    public void findLove(){
        System.out.println("儿子要求:肤白貌美大长腿");
    }
}

2.定义代理对象
public class CGlibMeipo implements MethodInterceptor {
    //1.定义接受真实对象处理,返回一个代理对象
    public Object getInstance(Class<?> clazz) throws Exception{
        //相当于Proxy,代理的工具类
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /*
    o:被代理的对象。即原始对象,也就是目标类的实例。
	method:要被调用的方法对象。即将要执行的目标方法。
	objects:方法的参数数组。即目标方法的参数列表。
	methodProxy:方法的代理对象。通过该对象可以调用目标方法。使用methodProxy.invokeSuper(o, objects)可以触发目标方法的执行。
    */
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object obj = methodProxy.invokeSuper(o,objects);
        after();
        return obj;
    }

    private void before(){
        System.out.println("我是媒婆,我要给你找对象,现在已经确认你的需求");
        System.out.println("开始物色");
    }
    private void after(){
        System.out.println("OK的话,准备办事");
    }
}

3.测试
public class CglibTest {
	public static void main(String[] args) {
        try {
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"E://cglib_proxy_classes");//打印代理对象生成的class文件
            //CGlibMeipo代理对象绑定真实对象并返回代理对象
            Customer obj = (Customer) new CGlibMeipo().getInstance(Customer.class);
            //执行代理对象方法并调用真实对象
            obj.findLove();
        } catch (Exception e) {
            e.printStackTrace();
        }
	}
}


六. 代理模式的优缺点

代理模式具有以下优点
(1)代理模式能将代理对象与真实被调用目标对象分离

(2)在一定程度上降低了系统的耦合性,扩展性好

(3)可以起到保护目标对象的作用

(4)可以增强目标对象的功能

当然,代理模式也有缺点
( 1)代理模式会造成系统设计中类的数量增加

(2)在客户端和目标对象中增加一个代理对象,会导致请求处理速度变慢.

(3)增加了系统的复杂度

七. JDK Proxy和CGLib比较

JDK是采用读取接口的信息
CGLib覆盖父类方法
目的:都是生成一个新的类,去实现增强代码逻辑的功能
JDK Proxy 对于用户而言,必须要有一个接口实现,目标类相对来说复杂
CGLib 可以代理任意一个普通的类,没有任何要求
CGLib 生成代理逻辑更复杂,效率,调用效率更高,生成一个包含了所有的逻辑的FastClass,不再需要反射调用
JDK Proxy生成代理的逻辑简单,执行效率相对要低,每次都要反射动态调用
CGLib 有个坑,CGLib不能代理final的方法文章来源地址https://www.toymoban.com/news/detail-796388.html

到了这里,关于3_代理模式(动态代理JDK原生和CGLib)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JDK动态代理和CGLIB动态代理

    JDK动态代理和CGLIB动态代理 ① JDK动态代理只提供接口的代理,不支持类的代理,要求被代理类实现接口。JDK动态代理的核心是InvocationHandler接口和Proxy类,在获取代理对象时,使用Proxy类来动态创建目标类的代理类(即最终真正的代理类,这个类继承自Proxy并实现了我们定义的

    2024年02月07日
    浏览(31)
  • 【动态代理】JDK动态代理与cglib动态代理源码解析

    UserService ,接口类 UserServiceImpl ,实现类 使用代理,测试效果。 控制台输出: Proxy#newProxyInstance ,生成代理类的实例。 核心在于 getProxyClass0 ,生成代理类的类信息 使用自定义的InvocationHandler作为参数,调用构造函数获取代理类对象实例 WeakCache#get ProxyClassFactory#apply ,实现了

    2024年02月04日
    浏览(30)
  • cglib动态代理、jdk动态代理及spring动态代理使用

    NickelBeforeAdvice.java方法执行之前 NickelAfterReturningAdvice.java方法执行之后 NickelAroundadvice.java环绕方法 NickelThrowAdvice.java抛异常方法 UserService.java抛异常方法 SpringProxtFactoryTest.java测试方法 NickelStaticMethodMatherPointcut.java方法匹配的方法 NickelPointcutAdvisor.java切面方法 SpringProxtFactoryTest.j

    2024年02月15日
    浏览(36)
  • 【spring】jdk动态代理和cglib动态代理的区别

    一、说明 1.spring aop中的动态代理主要有两种方式,jdk动态代理和cglib动态代理 2.从实现接口、继承父类的角度讨论区别 3.从限制角度讨论区别 4.从性能上讨论区别 二、区别 1.jdk动态代理只提供接口类的代理,如果目标类不是接口,只能用cglib代理 2.jdk动态代理会在运行时为目

    2024年02月16日
    浏览(31)
  • 通俗易懂 快速理解 JDK动态代理 和 cglib动态代理

    动态代理的实现方案有两种, JDK动态代理 和 CGLIB动态代理 ,区别在于JDK自带的动态代理,必须要有接口,而CGLIB动态代理有没有接口都可以。 JDK动态代理 :JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求 代理对象和目标对象实现同样的接口 (兄

    2024年02月08日
    浏览(35)
  • SpringAOP-说说 JDK动态代理和 CGLIB 代理

    Spring 的 AOP 是通过动态代理来实现的,动态代理主要有两种方式 JDK 动态代理和 Cglib 动态代理,这两种动态代理的使用和原理有些不同。 JDK 动态代理 Interface :JDK动态代理是基于接口的代理,它要求目标类实现一个接口。 InvocationHandler :InvocationHandler 是一个接口,可以通过

    2024年01月18日
    浏览(34)
  • 代理模式以及静态代理、JDK代理、Cglib代理的实现

    介绍 1、代理模式:为对象 提供一个替身 ,以控制对这个对象的访问,即通过代理对象访问目标对象,这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作 (即: 扩展目标对象的功能 ,例如Spring AOP) 2、被代理的对象可以是 远程对象 ,创建开销大的对象

    2024年03月12日
    浏览(34)
  • AOP、AspectJ、JDK动态代理、CGLIB

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、日志记录管理等。 AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类。 其中静态代理是

    2024年02月11日
    浏览(27)
  • Spring Boot 中的 AOP,到底是 JDK 动态代理还是 Cglib 动态代理

    大家都知道,AOP 底层是动态代理,而 Java 中的动态代理有两种实现方式: 基于 JDK 的动态代理 基于 Cglib 的动态代理 这两者最大的区别在于基于 JDK 的动态代理需要被代理的对象有接口,而基于 Cglib 的动态代理并不需要被代理对象有接口。 那么,Spring 中的 AOP 是怎么实现的

    2024年02月12日
    浏览(24)
  • springAop使用的动态代理是jdk还是cglib

    Spring AOP使用的动态代理可以是JDK动态代理或CGLIB动态代理,具体选择哪种代理方式取决于被代理的目标对象的类型和配置。 当被代理的目标对象实现了至少一个接口时,Spring AOP会默认使用JDK动态代理。JDK动态代理基于接口生成代理类,通过反射机制调用目标对象的方法。 而

    2024年02月09日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包