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


猜你喜欢
- 一、什么是封装?封装就是将属性私有化,提供公有的方法访问私有属性。做法就是:修改属性的可见性来限制对属性的访问,并为每个属性创建一对取值(g
- 写完js倒计时,突然想用java实现倒计时,写了三种实现方式一:设置时长的倒计时;二:设置时间戳的倒计时;三:使用java.util.Tim
- 本文实例讲述了java实现基于SMTP发送邮件的方法。分享给大家供大家参考。具体实现方法如下:import java.util.Date;i
- 目前知道的情况被调用的C/C++函数只能是全局函数 不能调用类中的成员方法被调用的C函数必须使用extern “C“包含,保证采用的导出函数
- 概述新版的音悦台 APP 播放页面交互非常有意思,可以把播放器往下拖动,然后在底部悬浮一个小框,还可以左右拖动,然后回弹的时候也会有相应的效
- 将jar包发布到Maven中央仓库(Maven Central Repository),这样所有的Java开发者都可以使用Maven直接导入
- 自从使用 HttpClient 和 Jsoup 配合编写了几个简单的入门爬虫之后,发现对于绝对路径的需求是很频繁的,因为大部分的网页都写相对
- 废话少说,直接上代码:ehcache.xml 文件<?xml version="1.0" encoding=&qu
- 目录引言编译环境及说明图片素材分割事件处理OnPaint事件鼠标交互事件代码汇总引言我们有时候会在程序的文件夹里看见一些图标,而这些图标恰好
- 最近项目里涉及到自定义View的东西还是挺多的,所以打算在自定义View上多花点时间,也顺便分享给大家。先总结下自定义View的步骤:1、自
- 前言当初年少懵懂,那年夏天填志愿选专业,父母听其他长辈说选择计算机专业好。从那以后,我的身上就有了计院深深的烙印。从寝室到机房,从机房到图书
- String类中的concat()方法的使用concat(String str)用法concat(String string) 返回值是St
- 当屏幕变为横屏的时候,系统会重新呼叫当前Activity的OnCreate方法,你可以把以下方法放在你的OnCreate中来检查当前的方向,
- Android Build类的详解及简单实例一、类结构:java.lang.Object? android.os.Build二、类概述:从系
- AnimationListener听名字就知道是对Animation设置 * ,说简单点就是在Animation动画效果开始执行前,执行完毕
- 执行引擎也只有几个概念, JVM方法调用和执行的基础数据结构是 栈帧, 是内存区域中 虚拟机栈中的栈元素, 每一个方法的执行就对应着一个栈帧
- 一、常见问题所有的final修饰的字段都是编译期常量吗?如何理解private所修饰的方法是隐式的final?说说final类型的类如何拓展
- 传输层安全性协议(英语:Transport Layer Security,缩写作 TLS),及其前身安全套接层(Secure Sockets
- 一、准备环境1.activiti软件环境1)JDK1.6或者更高版本;2)支持的数据库有:h2, mysql, oracle, postgr
- 在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程) 用个比较通俗的比如,任何一个守