栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDK代理模式学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDK代理模式学习笔记

JDK代理 1,代理模式

代理模式是指,为其他对象提供一种代理控制这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用。

换句话说,使用代理对象,是为了在不修改目标对象的基础上,增强业务逻辑。

**客户类真正的想要访问的对象是目标对象,但是客户类真正可以访问的对象是代理对象。**客户类对目标对象的访问是通过访问代理对象来实现的。当然,代理类与目标类要实现同一个接口。

例如: 有 A,B,C 三个类, A 原来可以调用 C 类的方法, 现在因为某种原因 C 类不允许 A 类调用其方法,但 B 类可以调用 C 类的方法。A 类通过 B 类调用 C 类的方法。这里 B 是 C 的代理。 A 通过代理 B 访问 C.

Window 系统的快捷方式也是一种代理模式。快捷方式代理的是真实的程序,双击快捷 方式是启动它代表的程序。

2,使用代理模式的作用

1,功能增强: 在你原有的功能基础上,增加了额外的功能,新增加的功能,叫做功能增强。

​ 功能增强的三种方式:

​ 1,增强参数列表。

​ 2,增强返回值类型。

​ 3,增强方法体执行逻辑。

2,控制访问: 代理类不让你访问目标类,例如商家不让客户访问厂家。

3,实现代理的方式

实现代理的方式分为:静态代理,动态代理。

3.1,静态代理 3.1.1,静态代理概念

静态代理是指,代理类在程序运行前就已经定义好.java源文件,其与目标类的关系在程序运行前就已经确立。在程序运行前,代理类已经编译为.class文件。

(1)代理类是自己实现的,自己创建一个java类,表示代理类。

(2)同时你所要代理的目标类是确定的。

3.1.2,静态代理的优缺点

(1)优点:

​ 1,容易理解

​ 2,实现简单

(2)缺点:

​ 当你的项目中,目标类和代理类很多的时候有以下缺点:

​ 1,代码复杂,难于管理

​ 代理类和目标类实现了相同的接口,每个代理类都需要实现目标类的方法,这样就出现了大量的代码重复。如果接口中增加 了一个方法,处理目标类需要实现这个方法外,所有代理类也需要实现这个方法。增加了代码维护的复杂度。

​ 2,代理类依赖目标类,代理类过多

​ 代理类只服务于一种类型的目标类,如果要服务多个类型,势必要为每一种目标类都创建代理类,静态代理在程序规模稍 大时就无法胜任了。代理数量过多。

3.1.3,静态代理的实现步骤

(1)定义业务接口

​ 定义业务接口,其中含有抽象方法,该抽象方法是目标方法**。**

(2)定义接口实现类(目标类)

​ 目标类实现了业务接口。

(3)定义代理类

​ 代理类也实现了业务接口,并在其中访问目标类。

(4)客户端调用者

​ 使用代理类,访问目标类。

3.2,动态代理 3.2.1,动态代理的概念

动态代理是值代理对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的.java源文件。

动态代理其实就是在jdk运行期间,动态创建class字节码并加载到JVM

总结:动态代理就是在程序组执行过程中,使用jdk的反射机制,创建一个代理类,并动态地指定代理目标类。

在静态代理中目标类很多的时候,可以使用动态代理,避免静态代理的缺点。(动态代理中,即使目标类很多,1,代理类数量可以很少;2,当你修改接口中的方法时,不会影响代理类)

3.2.2,动态代理的分类

动态代理的实现方式分为两类:

**(1)jdk动态代理(理解):**使用java反射包中的类和接口实现动态代理的功能。

​ 反射包java.lang.reflect里面有三个类:invocationHandler,Method,Proxy。

**(2)cglib动态代理(了解):**cglib是第三方的工具库,创建代理对象。

​ cglib的原理是继承,cglib通过继承目标类,在子类中重写父类中同名的方法,实现功能的修改。

​ 因为cglib是继承,重写方法,所以要求目标类不能是final的,方法也不能是final的。

​ cglib的要求目标类比较宽松,只要能够继承就行。cglib在很多框架中使用,比如mybatis,spring

3.2.3,jdk的动态代理

1,概念:jdk动态代理是基于Java的反射机制实现的。使用jdk中接口和类山西爱你代理对象的动态穿建。

​ jdk的动态要求目标对象必须实现接口,这是java设计上的要求(代理对象必须和目标对象实现相同的接口)

2,从jdk1.3以来,java语言通过java.lang.reflect包中提供的三个类来支持代理模式:Proxy,Method,InovcationHandler。

​ (1)InvocationHandler接口

​ InvocationHandler接口叫做调用处理器,负责完成完成调用目标方法,并增强功能。

​ 通过代理对象执行目标接口中的方法,会把方法的调用分派给调用处理器的实现类,执行实现类中的invoke()方法,我们 需要把功能代理写在invoke()方法中。

​ 接口中只有一个方法:

			public Object invoke(Object proxy,Method method,Object[] args)throws Throwable;

​ 在invoke方法中可以街区对目标方法的调用。在这里可以进行功能增强。Java的动态代理是建立在反射机制之上的。

​ 实现了InvocationHandler接口的类**用于加强目标类的业务逻辑。**具体加强逻辑的代码定义在invoke方法中,通过代理对象执 行接口中的方法时,会自动调用invoke()方法。

​ invoke方法的介绍如下:

​ 参数:

​ 1,Proxy proxy :jdk创建的代理对象,无需赋值。

​ 2,Method method:目标类中的方法,jdk提供

​ 3,Object[] args:目标类中方法的参数,jdk提供。

(2)Method 类

​ invoke()方法的第二个参数为Method类对象,该类有一个方法也叫invoke(),可以调用目标方法,这两个invoke()方法虽 然同名,但无关。

		public Object invoke ( Object obj, Object... args)

​ 参数:

​ 1,Object obj :代表目标对象

​ 2,args:表是目标方法的参数,就是其上一层invoke方法的第三个参数。

​ 该方法的作用是:调用执行 obj 对象所属类的方法,这个方法由其调用者 Method 对象确定。

(3)Proxy类

​ 通 过 JDK 的 java.lang.reflect.Proxy 类 实 现 动 态 代 理 , 会 使 用 其 静 态 方 法 newProxyInstance(),依据目标对象、业务 接口及调用处理器三者,自动生成一个动态代理对象。

		public static newProxyInstance ( ClassLoader loader, Class[] interfaces, InvocationHandler 				handler)

​ 参数:

​ 1,ClassLoader loader: 目标类的类加载器,通过目标对象的反射可获取。

​ 一般使用:

			真实对象.getClass().getClassLoader();

​ 2,Class interfaces:目标类实现的接口数组,通过目标对象的反射可获取。

​ 一般使用:

			真实对象.getClass().getInterfaces();

​ 3,InvocationHandler handler:调用处理器。

​ 一般使用匿名内部类,在invoke()方法中增强方法。new InvocationHandler();

3.2.4,jdk动态代理的实现

jdk 动态代理是代理模式的一种实现方式,其只能代理接口。

实现步骤:

1,新建一个接口,作为目标接口。

2,为接口创建一个实现类,是目标类。

3,创建类实现java.lang.reflect.InvocationHandler 接口,调用目标方法并增加其他功能代码。(可以使用匿名内部类)

4,创建动态代理对象,使用Proxy.newProxyInstance()方法,并把返回值强制转为接口类型。

具体实现:

(1)定义目标接口

package 动态代理;
//目标接口
public interface UsbSell {
    float sell(int amount);
}

(2)实现目标接口实现类

package 动态代理.Factory;

import 动态代理.UsbSell;
//金士顿厂商
//目标类
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        return 20*amount;
    }
}

(3)定义调用处理程序 (4)创建动态代理对象

package 动态代理.Shop;

import 动态代理.Factory.UsbKingFactory;
import 动态代理.UsbSell;

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

public class TaoBao {
    public static void main(String[] args) {
        //创建代理对象,使用Proxy
        //1,创建目标对象
        UsbSell king=new UsbKingFactory();
        //2,创建代理对象
        //使用匿名内部类的形式创建InvocationHandler对象
        UsbSell proxy = (UsbSell) Proxy.newProxyInstance(king.getClass().getClassLoader(), king.getClass().getInterfaces(), new InvocationHandler() {
            //重写invoke方法。
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //向厂家发送订单,即调用厂家的sell方法
                Object res = method.invoke(king, args);
                //进行功能增强
                float price=0;
                if(res!=null){
                    price=(float)res+20;
                }
                //增加其他功能
                System.out.println("恭喜您,获得10元优惠券");
                return price;
            }
        });
        //使用代理对象执行方法
        float price = proxy.sell(1);
        System.out.println("通过动态代理对象,调用方法:"+price);
    }


}

3.2.5,动态代理的作用

可以在不改变原来目标方法功能的前提下, 可以在代理中增强自己的功能代码。
程序开发中的意思。
比如:你所在的项目中,有一个功能是其他人(公司的其它部门,其它小组的人)写好的,你可以使用。
GoNong.class , Gonong gn = new Gonong(), gn.print();

你发现这个功能,现在还缺点, 不能完全满足我项目的需要。 我需要在gn.print()执行后,需要自己在增加代码。
用代理实现 gn.print()调用时, 增加自己代码, 而不用去改原来的 GoNong文件。

增强功能一般的使用方法

**1,增强参数:**可以通过args获取参数,修改之后再传给Method. invoke()方法。

2,增强返回值类型:在return中修改

**3,增强方法体:**在invoke方法中修改逻辑

注意:可以在invoke()方法中,判断方法名,给不同的方法不同的增强。

4,cgLib 代理

CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的 Code 生成类 库,它可以在运行期扩展 Java 类与实现 Java 接口。它广泛的被许多 AOP 的框架使用,例如 Spring AOP。 使用 JDK 的 Proxy 实现代理,要求目标类与代理类实现相同的接口。若目标类不存在 接口,则无法使用该方式实现。 但对于无接口的类,要为其创建动态代理,就要使用 CGLIB 来实现。CGLIB 代理的生成 原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用 CGLIB 生成动态代理,要求目标类必须能够被继承,即不能是 final 的类。 cglib 经常被应用在框架中,例如 Spring ,Hibernate 等。Cglib 的代理效率高于 Jdk。对 于 cglib 一般的开发中并不使用。做了一个了解就可以。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/759031.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号