Java * 之 * 的应用
作者:Haozz_1994 发布时间:2022-11-24 11:18:55
由于 * 一般都比较难理解,程序设计者会设计一个 * 接口供开发者使用,开发者只要知道 * 接口的方法、含义和作用即可,无须知道 * 是怎么实现的。用JDK * 来实现一个 * 的逻辑,为此先定义 * 接口Interceptor,如下所示:
/**
* @Auther: haozz
* @Date: 2018/5/27 22:15
* @Description: * 接口
**/
public interface Interceptor {
boolean before(Object proxy, Object target, Method method,Object[] args);
void around(Object proxy,Object target,Method method,Object[] args);
void after(Object proxy,Object target,Method method,Object[] args);
}
这里定义了3个方法,before、around、after方法,分别给予这些方法如下逻辑定义:
3个方法的参数为:proxy代理对象、target真实对象、method方法、args运行方法参数;
before方法返回boolean值,它在真实对象前调用。当返回为true时,则反射真实对象的方法;当返回为false时,则调用around方法;
在before方法返回为false的情况下,调用around方法
在反射真实对象方法或者around方法执行之后,调用after方法
实现这个Interceptor的实现类——MyInterceptor,如下:
/**
* @Auther: haozz
* @Date: 2018/5/27 22:48
* @Description:MyInterceptor
**/
public class MyInterceptor implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法前逻辑");
return false;//不反射被代理对象原有方法
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("取代了被代理对象的方法");
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法后逻辑");
}
}
它实现了所有Interceptor接口的方法,使用JDK * ,就可以去实现这些方法在适当时的调用逻辑了。以上一篇(Java设计模式之 * )中的接口和实现类为例,在JDK * 中使用 * ,如下所示:
/**
* @Auther: haozz
* @Date: 2018/5/27 22:30
* @Description:
**/
public class InterceptorJdkProxy implements InvocationHandler {
private Object target;//真实对象
private String interceptorClass = null;// * 全限定名
public InterceptorJdkProxy(Object target,String interceptorClass){
this.target = target;
this.interceptorClass = interceptorClass;
}
public static Object bind(Object target,String interceptorClass){
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InterceptorJdkProxy(target,interceptorClass));
}
@Override
/**
* Description:通过代理对象调用方法,首先进入这个方法
* @auther: haozz
* @param: proxy 代理对象
* @param: method 被调用方法
* @param: args 方法的参数
* @return: java.lang.Object
* @date: 2018/5/27 23:00
**/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(interceptorClass == null){
//没有设置 * 则直接反射原有方法
return method.invoke(target,args);
}
Object result = null;
//通过反射生成 *
Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).newInstance();
//调用前置方法
if(interceptor.before(proxy,target,method,args)){
//反射原有对象方法
result = method.invoke(target,args);
}else{//返回false执行around方法
interceptor.around(proxy,target,method,args);
}
//调用后置方法
interceptor.after(proxy,target,method,args);
return result;
}
}
这里有两个属性,一个是target,它是真实对象;另一个是字符串interceptorClass,它是一个 * 的全限定名。解释以下这段代码的执行步骤:
第1步,在bind方法中用JDK * 绑定了一个对象,然后返回代理对象;
第2步,如果没有设置 * ,则直接反射真实对象的方法,然后结束,否则进行第3步;
第3步,通过反射生成 * ,并准备使用它;
第4步,调用 * 的before方法,如果返回为true,反射原来的方法;否则运行 * 的around方法;
第5步,调用 * 的after方法;
第6步,返回结果。
开发者只要知道 * 的作用就可以编写 * 了,编写完后可以设置 * ,这样就完成了任务,所以对于开发者而言相对简单了
设计者可能是精通Java的开发人员,他来完成 * 的逻辑
设计者只会把 * 接口暴露给开发者使用,让 * 的逻辑在开发者的视野中“消失”
* 可以进一步简化 * 的使用方法,使程序变得更简单,用如下的测试类测试一下:
public class Mytest {
public static void main(String []args){
HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.csdn.blog.interceptor.MyInterceptor");
proxy1.sayHelloWorld();
}
}
运行这段代码,得到以下结果:
反射方法前逻辑
取代了被代理对象的方法
反射方法后逻辑
显然, * 已经生效。
来源:https://blog.csdn.net/hz_940611/article/details/80473696
猜你喜欢
- 在使用C#进行桌面应用开发中,经常会有对文件进行操作的情况,这时可能会需要对文件夹进行文件扫描,获取所有文件做法如下/// <summ
- 基于创蓝253短信服务平台的Java调用短信接口APIpackage com.bcloud.msg.http;import java.io.
- 在Google I/O 2017中,Google 宣布 Kotlin 成为 Android 官方开发语言。为什么选择 Kotlin? 简洁:
- 背景大家在使用Selenium + Chromedriver爬取网站信息的时候,以为这样就能做到不被网站的反爬虫机制发现。但是实际上很多参数
- 在Springboot项目中使用分页插件的时候 发现PageHelper插件失效了我导入的是:后来才发<dependency>
- 在C#中 “\”是特殊字符,要表示它的话需要使用“\\”。由于这种写法不方便,C#语言提供了@对其简化。只要在字符串前加上@即可直接使用“\
- 如果我们在浏览器地址栏乱敲的时候,所敲入的所有未定义的URL都能被程序捕捉到,然后转到一个自制的404错误处理页面。先看效果图登陆页面主页面
- 编写程序,事先将所有观众姓名输入数组,然后获得数组元素的总数量,最后在数组元素中随机抽取元素的下标,根据抽取的下标获得幸运观众的姓名。思路如
- 前言本文主要给大家介绍的是关于obix协议在java中的配置和使用,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。什么是
- 最近在项目过程中遇到了保存数据的需求,对实体类的部分数据进行保存,打算采用反射+自定义特性来实现数据保存,利于扩展1. 采用反射实现能够灵活
- 本文实例为大家分享了Java实现简单万年历的具体代码,供大家参考,具体内容如下1 要求1、输入年份;2、输入月份;3、输出某年某月的日历。2
- 服务器端我们用软件模拟,是一个很小巧的软件,下载软件NetAssist:http://xiazai.jb51.net/201403/tool
- 其实写到这里,我已经差不多断气了。。。常规套路,这里是前三篇的传送门,需要的同学可以看一下:JAVA写文本编辑器(三) JAVA写文本编辑器
- 1.鼠标右击我的电脑–》属性–》高级系统设置2.把下面的变量名称和电脑文件的本地路径填进去即可(注意:变量值后面后面不要带分号)jdk环境变
- spring boot与profilespring boot 的项目中不再使用xml的方式进行配置,并且,它还遵循着约定大于配置。静态获取方
- 本文实例为大家分享了java读取cvs文件并导入数据库的具体代码,供大家参考,具体内容如下首先获取文件夹下面的所有类型相同的excel,可以
- Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,是一种比较常用
- JAVA枚举,比你想象中还要有用!我经常发现自己在Java中使用枚举来表示某个对象的一组潜在值。在编译时确定类型可以具有什么值的能力是一种强
- Java接口回调产生接口回调的场景在现实生活中,产生接口回调的场景很简单,比如我主动叫你帮我做一件事,然后你做完这件事之后会通知我,&quo
- Java Tess4J实现图像识别最近需要用Java做一个图像识别的东西,查了一些资料,在此写一个基于Tess4J的教程,方便其他人参考和使