首页 > 编程知识 正文

动态代理设计模式,微商代理机制

时间:2023-05-06 10:23:45 阅读:138220 作者:3750

文章目录代理模式1、使用代理模式的作用2、实现代理的方式3、静态代理4、动态代理4.1、JDK动态代理4.1.1、JDK动态代理4.1.2是什么

代理模式

代理模式是指为其他对象提供代理以控制对该对象的访问。 虽然一个对象可能不适合或不能直接引用另一个对象,但代理对象可以在客户类和目标对象之间起中介作用。

换句话说,使用代理对象是为了在不修改目标对象的情况下增强主要业务逻辑。

客户类真正希望访问的对象是目标对象,而客户类真正有权访问的对象是代理对象。 对客户端类目标对象的访问是通过访问代理对象来实现的。 代理类和目标类实现相同的接口。

例如,有三个类别: a、b和c。 a类本来可以调用c类方法。 虽然c类由于某种原因不允许a类调用该方法,但b类可以调用c类方法,而a类可以通过b类调用c类方法。 这里b是c的代理,a通过代理b访问c。

原始访问关系:

通过代理的访问关系:

例如,Windows系统的快捷方式也是代理模式。 快捷方式代理是真的程序,双击的快捷方式是启动它所表示的程序。

1、使用代理模式的作用、功能强化:在以往的功能中增加了额外的功能。 新添加的功能称为功能扩展。

、控制访问:代理类不允许访问目标。 例如,商家类似于不让用户访问制造商。

2 .实现代理的方式静态代理和动态代理。

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

静态代理的实现步骤:

(1)、定义接口及其实现类;

)2)、创建代理类同时实现该接口;

)3)、将目标对象注入代理类,用代理类的对应方法调用目标类中的对应方法。 这样,您就可以通过代理类阻止对目标对象的访问,并在执行目标方法前后做自己想做的事情。

特点:实现简单,容易理解。

模拟业者在陶宝和京东购买笔记本电脑的例子:

定义业务接口

//业务接口LaptopSell (目标接口) publicinterfacelaptopsell定义抽象方法sell,其中sell是目标方法floatsell(intamount ) }定义接口实现类:

//LenovoLaptopFactory目标类。 实现业务接口publicclasslenovolaptopfactoryimplementslaptopsell { @ overridepublicfloatsell (int amount ) }的代理商TaoBao

publicclasstaobaoimplementslaptopsell//商家代理的制造商是哪个privatelenovolaptopfactoryfactory=newlenovolaptopfactory (); @ overridepublicfloatsell (int amount ) /向制造商发送顶级订单,告诉制造商买了电脑,制造商发货)//如何调用目标类//制造商的价格//商家需要涨价。 即代理商增加价格price =100扩展功能,代理类在完成目标类的方法调用后,扩展了功能的return price; }代理商京东:

publicclassjingdongimplementslaptopsell { privatelenovolaptopfactoryfactory=newlenovolaptopfactory (; 调用@ overridepublicfloatsell (int amount )//目标类的方法floatprice=factory.sell; 预定义=90; return price; }客户调用者,购买商品类:

publicclassshopmain { publicstaticvoidmain (string [ ] args ) { float price=0.0f; TaoBao taoBao=new TaoBao (); price=Taobao.sell(1; system.out.println(price; system.out.println('========' ); 景东景东=new景东(; price=jingdong.sell(1) ) )。

; System.out.println(price); }}

图示:

静态代理的缺点:
1)、代码复杂,难于管理
代理类和目标类实现了相同的接口,每个代理都需要实现目标类的方法,这样就出现了大量的代码重复。如果接口增加一个方法,除了所有目标类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
2)代理类依赖目标类,代理类过多
代理类只服务于一种类型的目标类,如果要服务多个类型。势必要为每一种目标类都进行代理,静态代理在程序规模稍大时就无法胜任了,代理类数量过多。

4、动态代理

动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的Java源文件。
动态代理其实就是jdk运行期间,动态创建class字节码并加载到JVM。
动态代理的实现方式有两种:
1、使用JDK动态代理;
2、通过CGLIB动态代理;

4.1、JDK动态代理 4.1.1、什么是JDK动态代理

使用java反射包中的类和接口实现动态代理的功能。
JDK的动态代理要求目标对象必须实现接口

反射包 java.lang.reflect , 里面有三个类 : InvocationHandler , Method, Proxy.
一、InvocationHandler 接口(调用处理器)
就一个方法invoke(),
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke()方法中。
代理类完成的功能:
1、 调用目标方法,执行目标方法的功能
2、 功能增强,在目标方法调用时,增加功能。
方法原型:
参数: Object proxy: jdk创建的代理对象,无需赋值。
Method method: 目标类中的方法,jdk提供method对象的
Object[] args:目标类中方法的参数, jdk提供的。
public Object invoke(Object proxy, Method method, Object[] args)
InvocationHandler 接口:表示你的代理要干什么。
怎么用:
1.创建类实现接口InvocationHandler;
2.重写invoke()方法, 把原来静态代理中代理类要完成的功能,写在这。

二、Method类
表示方法的, 确切的说就是目标类中的方法。
作用:通过Method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法的参数)
说明: method.invoke()就是用来执行目标方法的,等同于静态代理中的
向厂家发送订单,告诉厂家,我买了Laptop,厂家发货
float price = factory.sell(amount);

三、Proxy类
核心的对象,创建代理对象。之前创建对象都是 new 类的构造方法()。
现在我们是使用Proxy类的方法,代替new的使用。
方法: 静态方法 newProxyInstance()
作用是: 创建代理对象, 等同于静态代理中的TaoBao taoBao = new TaoBao();
参数:

ClassLoader loader 类加载器,负责向内存中加载对象的。 使用反射获取对象的ClassLoader
类a , a.getCalss().getClassLoader(), 目标对象的类加载器Class<?>[] interfaces: 接口, 目标对象实现的接口,也是反射获取的。InvocationHandler h : 我们自己写的,代理类要完成的功能。
返回值:就是代理对象
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) 4.1.2、jdk动态代理的实现

实现步骤:
1、创建接口,定义目标类要完成的功能
2、创建目标类实现接口
3、创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
①、调用目标方法;
②、增强功能。
4、使用Proxy类的静态方法,创建代理对象。并把返回值转为接口类型。
定义目标接口:

public interface LaptopSell { float sell(int amount);}

定义目标接口实现类:

public class LenovoLaptopFactory implements LaptopSell { @Override public float sell(int amount) { return 5550.0f; }}

定义调用处理程序:

public class MySellHandler implements InvocationHandler { private Object target = null; public MySellHandler() {} //使用构造方法传入目标对象,给目标对象完成代理功能 public MySellHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //执行目标方法 Object ret = method.invoke(target,args); float price = (float) ret; //在目标方法执行完后增强功能 ret = price + 100; return ret; }}

创建动态代理对象:

public class MainShop { public static void main(String[] args) { //创建目标对象 LaptopSell factory = new LenovoLaptopFactory(); //创建InvocationHandler对象 InvocationHandler handler = new MySellHandler(factory); //创建代理对象 LaptopSell proxy = (LaptopSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(),handler); //通过代理对象执行目标方法 System.out.println(proxy.sell(1)); }}

图示:

类图:

4.2、CGLIB代理

CGLIB (opens new window)(Code Generation Library)是一个基于ASM (opens new window)的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB 通过继承方式实现代理。很多知名的开源框架都使用到了CGLIB (opens new window), 例如 Spring 中的 AOP 模块中:如果目标对象实现了接口,则默认采用 JDK 动态代理,否则采用 CGLIB 动态代理。

JDK 动态代理和 CGLIB 动态代理对比:
1、JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。
2、就二者的效率来说,大部分情况都是 JDK 动态代理更优秀。

5、静态代理和动态代理的对比

①、动态代理更加灵活,不需要必须实现接口,可以直接代理实现类,并且可以不需要针对每个目标类都创建一个代理类。静态代理中,接口一旦新增加方法,目标对象和代理对象都要进行修改,非常麻烦。
②、静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。而动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。