首页 > 编程知识 正文

jdk动态代理源码分析,jdk动态代理底层原理

时间:2023-05-06 10:50:55 阅读:31864 作者:280

基于动态代理(理解)反射机制

1 .什么是动态代理? 使用jdk反射机制创建对象的能力是在代理类中创建对象。 不需要创建类文件。 不需要写java文件。

动态:调用jdk提供的方法,在程序运行时创建代理类的对象。

jdk动态代理,需要接口,目标类需要实现接口,没有接口时需要使用cglib动态代理

2 .你知道动态代理能做什么吗? 可以在代理中扩展自己的功能代码,而不更改原始目标方法的功能。 程序开发中的意思。

例如,你所在的项目具有别人(公司其他部门、其他集团的人)写的功能。 可以使用。

-----GoNong.class,GoNong gn=new GoNong (,gn.print );

你发现这个功能,至今仍有缺点,不能完全满足我项目的需要。 gn.print ()运行后,我需要自己增加代码。

在代理上实现gn.print ()调用时,请添加自己的代码,而不是修改原始GoNong文件。

开发中也有这样的事情。 你有a类。 本来调用c类的方法来完成某个功能。 但是,c不让a呼叫。

不能调用a -----的方法。

在a和c中直接创建b代理,c让b访问。

访问a --访问--C

实际范例:登录,注册验证码,验证码是手机短信。

中国移动,联通可以发短信。

中国移动、联通有子公司或关联方,他们为社会提供短信发送功能

fzdlq项目发送邮件-----子公司或子公司-----中国移动、联通

3 .使用代理模式增强功能:在你原来的功能中增加了额外的功能。 新添加的功能称为功能扩展。 访问控制:代理类不允许目标访问。 例如,商家不让用户访问制造商。 4 .实现代理的方式1 .静态代理:代理类自己手工实现,自己创建表示代理类的java类。 同时,你代理的目标类已经确定。 特征)1)实现简单;2 )简单易懂。 缺点:在jzdhy项目中,如果目标类和代理类较多,则存在以下缺点:

1 )随着目标类的增加,代理类可能也需要加倍。 代理数量太多了。

2 )在jzdhy接口中添加或修改功能会影响许多实现系统、制造商系统和代理。 影响比较多。 例:模拟一个用户购买u盘的行为。 用户是客户端类

商家:代理,代理某个品牌的u盘。

制造商:目标类。

三方关系:用户(客户端)运营商;代理;制造商;目标)

商家和制造商正在销售u盘。 他们完成的功能一致,销售u盘。

实施步骤:

1 .创建一个定义如何销售u盘的接口,代表你的制造商和商家所做的。

2 .创建厂商类,实现一步界面

3 .做商家,是代理,需要实现一步界面。

4 .创建客户端类,调用商家的方法买一个u盘。

代理执行的功能:

1 .调用目标类中的方法

2 .增强权能

代码实现:

表示接口//功能的、制造商、商家要完成的功能public interface UsbSell { //定义方法参数amount:表示一次购买的数量,暂时以//返回值表示一个USB存储器的价格浮动销售(int amount; //其他方法可以有多个//void print (; (制造商) /目标类)金斯敦制造商不接受用户单独购买。 publicclassusbkingfactoryimplementsusbsell { @ overridepublicfloatsell (int amount ) { System.out.println目标类中的方法//后期通过amount,可以实现10000个、点击80,50000个75 return 85.0f等不同的价格; (}} //taobao是代理金斯敦u盘销售的公司。 publicclasstaobaoimplementsusbsell//声明代理商制造商具体是谁privateusbkingfactoryfactory=newusbkingfactory (); @ override//实现USB内存功能销售的publicfloatsell(intamount ) /向制造商发送订单,告知制造商已经买了USB内存,制造商将浮动价格=factory . //制造商的价格。 //商家需要涨价。 也就是说,代理商需要提高价格。 price=price 25; //扩展,代理类在完成目标类的方法调用后扩展了功能。 //调用目标类的方法后,您所做的所有其他功能都是增强的意思。 System.out.println (淘宝商,给你

返一个优惠券,或者红包"); //增加的价格 return price; }} 买家public class ShopMain { public static void main(String[] args) { //创建代理的商家taobao对象 TaoBao taoBao = new TaoBao(); //通过代理类,实现购买u盘,增加了优惠券,红包等等 float price = taoBao.sell(1); System.out.println("通过淘宝的商家,购买u盘单价:"+price); }} 2.动态代理

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

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

在java中,要想创建对象:

创建类文件, java文件编译为class使用构造方法,创建类的对象。 动态代理的实现:

jdk动态代理(理解): 使用java反射包中的类和接口实现动态代理的功能。
反射包 java.lang.reflect , 里面有三个类 : InvocationHandler , Method, Proxy.

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

jdk动态代理 反射, Method类,表示方法。类中的方法。 通过Method可以执行某个方法。 public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { //使用反射机制执行sayHello方法。 核心Method(类中的方法) HelloService target = new HelloServiceImpl(); //获取sayHello名称对于的Method类对象 Method method = HelloService.class.getMethod("sayHello", String.class); //通过Method可以执行sayHello方法调用 /* invoke是Method类中的一个方法。表示执行方法的调用 参数: 1. Object , 表示对象的,要执行这个对象的方法,任意实现HelloService接口对象 2. Object... args , 方法执行时的参数值 返回值: Object:方法执行后的返回值 */ HelloService service2 = new HelloServiceImpl2(); // 执行service2对象method(sayHello)方法,参数是“jmdc” Object ret = method.invoke(service2, "jmdc"); } jdk动态代理的实现
反射包 java.lang.reflect , 里面有三个类 : InvocationHandler , Method, Proxy.
1)InvocationHandler 接口(调用处理器):就一个方法invoke()
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在
invoke()方法中。

方法原型:

public Object invoke(Object proxy, Method method, Object[] args){}

参数:
----Object proxy: jdk创建的代理对象,无需赋值。
----Method method: 目标类中的方法,jdk提供method对象的
----Object[] args: 目标类中方法的参数, jdk提供的。

(1) InvocationHandler 接口:表示你的代理要干什么。
怎么用:

创建类实现接口InvocationHandler重写invoke()方法, 把原来静态代理中代理类要完成的功能,写在这。

(2) Method类:表示方法的, 确切的说就是目标类中的方法。

作用:通过Method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法的参数)
Object ret = method.invoke(service2, “jmdc”);

说明: method.invoke()就是用来执行目标方法的,等同于静态代理中的
//向厂家发送订单,告诉厂家,我买了u盘,厂家发货
float price = factory.sell(amount); //厂家的价格。

(3) 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)

实现动态代理的步骤:

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

动态代理实际代码:(两个类)

public class ServiceFactory {public static Object getService(Object service){//这里返回的是代理类对象return new TransactionInvocationHandler(service).getProxy();}} import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import org.apache.ibatis.session.SqlSession;public class TransactionInvocationHandler implements InvocationHandler{private Object target;public TransactionInvocationHandler(Object target){this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {SqlSession session = null;Object obj = null;try{session = SqlSessionUtil.getSqlSession();obj = method.invoke(target, args);session.commit();}catch(Exception e){session.rollback();e.printStackTrace();//处理的是什么异常,继续往上抛什么异常throw e.getCause();}finally{SqlSessionUtil.myClose(session);}return obj;}public Object getProxy(){return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);}}

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