SSH前言学习笔记(4)

动态代理的实现

前面我们已经实现了静态代理,现在我们来实现动态代理

着重学习两种动态代理:JDK动态代理、CGLIB动态代理

(1)我们先将之前的01-staticProxy1复制粘贴,取名为02-dynamicProxy

之前说过,静态代理与动态代理的区别就是静态代理有代理类而动态代理没有,那么我们实现动态代理就需要将之前的动态代理类(com.QST.proxy包)删除

(2)、在MyTset类中将

ISomeService service=new ServiceProxy(target);
改为
ISomeService service= Proxy.newProxyInstance(loader, interfaces, h);

(关于Proxy的API可以参照JDK6API.chm的Proxy(JDK6API.chm资源已经放入下载))

然后进行更改:

ISomeService service= Proxy.newProxyInstance(
								target.getClass().getClassLoader(),//目标类的加载器 
									target.getClass().getInterfaces(), //目标类实现的所有接口
										h);

h其实是InvocationHandler(接口对象:接口的实现类的对象),对于h我们可以创建内部匿名类类【注1】

ISomeService service= Proxy.newProxyInstance(
								target.getClass().getClassLoader(),//目标类的加载器 
									target.getClass().getInterfaces(), //目标类实现的所有接口
										new InvocationHandler() { //内部匿名类
											
											@Override
											public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
												// TODO Auto-generated method stub
												return null;
											}
										});

此时会出现错误:Type mismatch: cannot convert from Object to ISomeService

其实是转换类型出现了错误,下面的解释是不能从Object到ISomeService接口进行转换,那么我们把光标放在出错行,Ctrl 1选择解决方案Add cast to “ISomeService”(即对Proxy进行强转)

变为(ISomeService)Proxy.newProxyInstance(...);

(3)、开始增强目标类中的目标方法

大家可以看到在内部匿名类中有三个参数:Proxy代理对象、method目标方法、args目标方法的参数列表

首先

在内部匿名类中加入代码:

method.invoke(obj, args);

将obj改为target

此时出现第二次错误:cannot refer to a non-final variable target inside an inner class defined in a different method

意思是在一个内部类中不能引用一个非final的变量target

我们可以选定target利用Ctrl 1将其改为final类型

然后对method.invoke进行抽取局部变量(Alt shift L)输入result


抽取之后

method.invoke(obj, args);
变为
Object result = method.invoke(target, args);

大家可以看到method.invoke的返回值默认为Object类型

然后

将return null;改为:

return ((String)result).toUpperCase();

对原本为Object类型的result进行强转,使其变为String类型

运行可以发现Console栏出现下面结果:


大家可以看到虽然对目标方法进行了强化并且执行了doSecond方法,但是却报了空指针异常

原因是在执行强化了doFirst方法之后会继续运行doSecond方法,此时也会调用内部匿名类,但是在抽取变量的时候发现doSecond方法并不像doFirst方法一样有abcde的返回值,相反doSecond方法没有返回值,所以result就是空的,才会报空指针的异常

我们可以将return的result进行抽取局部变量,把return语句变为:

String result = ((String)result).toUpperCase();
return result;

去掉String

然后全选语句result=((String)result).toUpperCase();   Alt Shift Z,弹出:


按5选择if得到:

if (condition) {
	result = ((String) result).toUpperCase();
						}

将if的条件改为result !=null

运行

得到:


成功消除空指针异常

完成动态代理实现

【注1】:内部匿名类:

new一个接口或者一个类的对象(本文new了一个InvocationHandler接口),但是没有名字

JDK6API中文版资源下载放在这里       https://pan.baidu.com/s/1nFxzVH1BJnJ6k7fU7G6GLQ

好像设置了密码,如果需要在下面留言我发一下(免费)

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值