动态代理学习

1.动态代理:基于反射机制。(理解)
2.代理:
1)什么是动态代理 :使用jak的反射机制,创建对象的能力,创建的是代理类的对象,而不用你创建类文件,不用谢java文件。
动态:在程序的执行时,调用jak提供的方法才能创建代理类的对象。

2)知道动态代理能做什么。

可以在不改变原来目标的功能的迁移下,可以在代理中增强自己的功能代码。
比如:你所在的项目,有一个功能是其他人(公司其他部门,其他小组的人)写好的,你可以使用
代理:
代购,中介,换ip。
留学中介(代理)
代理的特点:
1)中介和代理要做的事情是一致的:招生
2)中介是学校代理,学校是目标
3)家长–中介(学校接受,办入学手续)–美国学校。
4)中介是代理,不能白干活,需要收取费用。
5)代理不让你访问到目标
为什么找中介:
1)中介是专业的,方便
2)家长现在不能自己去找学校,家长没有能力访问学校,或者美国学校不接收个人来访。

开发中:a类向调用c类,但是c类不让a类调用
创建一个b代理,c让b访问,a访问b,b访问c。

登陆,注册时发送验证码
验证码是手机短信。
中国移动,联通能发短信。
中国移动,联通有子公司或关联公司,他们面向社会提供短信发送的功能
项目发送短信-资工作,或者关联公司-中国移动,联通。


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


使用代理的作用:
1.功能增强:在你原有的功能上,增加了额外的功能,新增加的功能,叫做功能增强。
2.控制访问:代理类不让你访问目标,例如商家不让用于访问厂家

4.实现代理的方式
1.静态代理:1)代理类是自己手工实现的,自己创建一个java类,表示代理类。
2)同时你所要代理的目标类是确定的
特点:1)实现简单。2)容易理解。
缺点:1)当目标类增加了,代理类可能也需要成倍的增加,代理类数量过多。
2)当接口中接口中的功能增加了,或者修改了,会影响总舵的实现类,厂家类,代理都需要修改
,影响比较多。
用户买u盘的行为:
用户是客户端
商家:代理,代理某个品牌的u盘
厂家:目标类
三者的关系:用户(客户端)–商家(代理)—厂家(目标)
商家和厂家都是卖u盘的,他们完成的功能是一致的。

实现步骤:
1.创建一个接口,定义卖u盘的方法,表示你的厂家和商家做的事情
2:创建厂家类,实现1步骤的接口
3:创建商家:就是dialing,也需要实现步骤1中的接口
4,创建客户类,调用商家的方法买一个u盘。

代理类的功能:
1.目标类的功能的完成
2.功能的增强

动态代理:在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理目标类,
换句话中,动态代理是一种创建java对象的能力,让你不用创建taobao类,就能创建代理类对象。

calss方法:
Field[] getFields()
返回一个数组包含 Field物体反射的类或接口的 类对象代表所有可访问的公共领域。
static 类<?> forName(String className) 返回与给定的字符串名称的类或接口相关的 类对象。 static 类<?> forName(String name, boolean initialize, ClassLoader loader)
返回 类对象相关的类或接口的给定的字符串名称,使用给定的类装载器。
Annotation[] getAnnotations()
返回此元素上的注释。
ClassLoader getClassLoader()
返回类的类装载器。
Constructor getDeclaredConstructor(类<?>... parameterTypes) 返回一个 Constructor对象反映指定的构造函数的类或接口的 类对象表示。 Constructor<?>[] getDeclaredConstructors()
返回 Constructor物体反射所有的构造函数通过 类对象表示的类中声明一个数组。
Field getDeclaredField(String name)
返回一个对象,反映了 Field指定声明字段的类或接口的 类对象表示。
Field[] getDeclaredFields()
返回 Field物体反射所有字段的类或接口的 类对象表示声明数组。
Field getField(String name)
返回一个 Field对象反映的类或接口的 类对象表示的指定公共成员。
Field[] getFields()
返回一个数组包含 Field物体反射的类或接口的 类对象代表所有可访问的公共领域。
方法 getMethod(String name, 类<?>… parameterTypes)
返回一个 方法对象反映的类或接口的 类对象表示的指定公共成员方法。
方法[] getMethods()
返回一个数组包含 方法物体反射所有的类或接口的 类对象表示的公共方法,包括那些由类或接口的超类和超接口继承的声明。

int getModifiers()
返回该类或接口的java语言的修饰,在整数编码。
String getName()
返回单位名称(类,接口,数组类,原始类型,或无效)的 类对象表示,作为一个 String。

方法 getDeclaredMethod(String name, 类<?>... parameterTypes) 返回一个 方法对象反映指定声明方法的类或接口的 类对象表示。 方法[] getDeclaredMethods() 返回一个数组包含 方法物体反射所有声明的方法的类或接口的 类对象,代表包括公众、保护,默认(包)的访问,和私有方法,但不包括继承的方法。 public 方法 getMethod(String name, 类<?>… parameterTypes)
throws NoSuchMethodException,
SecurityException
返回一个 方法对象反映的类或接口的 类对象表示的指定公共成员方法。这是一个 String name参数指定所需的方法简单的名字。
的 parameterTypes参数是 类对象识别方法的形参类型的数组,在声明的顺序。如果 parameterTypes是 null,它被看作是一个空数组。

在java中,要想创建对象:
1.创建类文件,java文件编译为class
2.使用构造方法,创建类的对象。

静态代理和动态代理模式的对比
在静态代理中目标很多的时候,可以使用动态代理,避免静态代理的缺点

在静态代理中目标类很多时候,可以使用动态代理,避免静态代理的缺点。
动态代理中目标类即使很多,

代理类数量可以很少,

当你修改了接口中的方法时,不会影响代理类。

动态代理:在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理目标类。
换句话说:动态代理是一种创建java象的能力,让你不用创建 TaoBao类就能创建代理类对象,除去了中间商

动态代理的实现:

jdk动态代理(理解):使用java反射包中的类和接口实现动态代理的功能,反射包java.lang.reflect,
里面有三个类:InvocationHandler,Method,Proxy
1)InvocationHandler 接口:(调用处理器)就一个方法invoke():表示代理对象要执行的功能代码,你的代理类要完成的
功能就写在invoke方法中。
方法原型:
参数:object proxy:jdk创建的代理对象,无需赋值。
Method method:目标类中的方法,jdk提供method对象的
object[]args:目标类中方法的参数,jdk提供的。
public Object invoke(Object proxy,Method method ,Object[] args}
双击shift可以查看源代码
怎么用:1.创建类实现接口Invocationhandler
2。重写invoke()方法,把原来静态代理中代理类要完成的功能,写在这个方法里面。

2)Method类:表示方法的,确切的说就是目标类中的方法
作用:通过Method可以执行某个目标类的方法 Method.invoke();
method.invoke(目标对象,方法的参数)
method.invoke(target,args)
//执行target的类中的方法,具体执行哪个方法,根据args而定
Object ret= method.invoke(service2,“lisi”);
说明:method.invoke()就是为了用来执行目标方法的,等同于静态代理中的

// 向厂家发送订单,告诉厂家,我买了U盘,厂家发货
// 发送给工厂,我需要的订单,返回报价
float price = factory.sell(amount);

proxy类:核心的对象,创建代理对象,之前创建对象都是new 类的构造方法();
现在我们是使用proxy类的方法,代替new的使用。
方法:静态方法 newproxyInstance()
作用是:创建代理对象,等同于静态代理中的TaoBao taoBao=new TaoBao()。
参数:
1.ClassLoder loader类加载器,负责向内存中加载对象的,使用反射获取对象的ClassLoader类a。
a.getCalss().getClassLoader(),目标对象的类加载器
Class<?>[] interfaces,接口,目标对象实现的结论,也是反射获取的。
InvocationHandler h :我们自己写的,代理类要完成的功能。

public static Object newProxyInstance(ClassLoder loader,
Class<?>[] interfaces,
InvocationHandler h)
float price=proxy.sell(1)
这个sell会传入给invoke方法的metod,1会传入args

代理类完成的功能:
1.调用目标的方法,执行目标方法的功能
2.功能增强,在目标调用时,增强功能。

cglib动态代理(了解): cglib是第三方的工具库,创建代理对象
cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中
重写父类中同名的方法,实现功能的修改。
因为cglib是继承,重写方法,所以要求目标类不能是fina1的,方法也不能是final的。
cglib的要求目标类比较宽松,只要能继承就可以了。cglib在很多的框架中使用,
比如mybatis,spring框架中都有使用。

jdk动态代理:
1.反射,method类,表示方法,类中的方法,通过method可以执行某个类。
HelloServiceImpl target=new HelloServiceImpl();
Method method=HelloService.class.getMethod(“sayhello”,String.class);
//通过Method可以执行类的一个方法。表示执行方法的调用
参数:
1.Object 表示对象的,要执行这个对象的方法
2.Object 。。。 args,方法执行的参数值
返回值:
Object:方法执行后的返回值
//表达的意思就是,执行target对象sayHello,参数李四。
Object ret=method.invoke(target,“李四”);
//如果调用另外一个类
HelloService service2=new HelloServiceImpl2();
Object ret=method.invoke(service2,“李四”);

这种方法必须有接口。

自己的想法:
接口-接口实现类(目标类)-商家(被动态代理了)-我
动态代理有什么好处:好处就是我可以不修改目标类的代码而进行增强,目标类代码的修改我也可以不改变
1.写接口
2.目标类实现接口
写myhandler实现nvocationHandler接口
定义invoke方法
写一个构造函数target,这个是作为传入对象的
//传入是谁的对象,就给谁创建代理
public MyHandle(Object target) {
this.target = target;
}

我---
         1.创建对象,使用Proxy

// 2.创建目标对象
UsbSell factory = new UsbKingFactory();
// 3.创建Invocationhandler对象
InvocationHandler myHandle = new MyHandle(factory);
//这里会将factory作为对象传入myhandler类传入invoke方法,表明我是实现了目标类

// 4.创建代理对象
UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
myHandle);
//这是一个proxy代理对象,用来代理myhandler,float price = proxy.sell(1);
实现myhandler的方法,传入参数值1

下面先说接口InvocationHandler的作用,看看官方文档对它的说明

InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.

翻译成中文:

InvocationHandler是由代理实例的调用处理程序实现的接口 。

每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。

也就是说我们代理类要调用目标对象(委托类)的方法都要经过InvocationHandler这个接口的invoke方法来调用。

看看InvocationHandler中唯一的一个方法invoke

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

三个参数的含义:

Object proxy:我们要代理的目标对象

Method method: 代理对象中实现了接口中方法的实例(这里有点抽象,其实就是代理对象实现了接口中的方法,这个方法也会调用目标对象(委托类)中的同一个方法)

Object [] args: 调用目标对象(委托类)中方法的参数

返回结果:目标对象类中的方法执行后返回的结果

这个方法看着是难以理解,但通过实际操作就比较容易了解这个方法的作用了,下面会有更详细的说明。

再看看Proxy类的官方文档对它描述

Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.

翻译成中文

Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。

说白了就是这个类提供了为我们创建代理类的方法,其中最常用的方法就是newProxyInstance()

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)throws IllegalArgumentException

三个参数的含义:

ClassLoader loader: 类加载器来定义代理类,用那个类加载器来加载代理对象

Class<?>[] interfaces: 代理类要实现的接口列表,就是代理类要实现哪些接口,这里是个数组,可以实现多个接口

InvocationHandler h:调度方法调用的调用处理函数(调用目标对象的handler)

返回结果:由指定的类加载器定义并实现指定接口的代理类的指定调用处理程序的代理实例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值