java接口中的default_java8 通过反射执行接口的default方法
最近更新light-dao遇到的。
需要在一个接口中增加default方法,同时需要对非default方法重写。
大概类似这样:
public interface BaseDao {
default String getName() {
return "name";
}
@Select("select * from ad")
List getAll();
}
我们重写的Handler类似这样:
public class DaoInvocationHandler implements InvocationHandler {
private Map sqlExecutorMap = new ConcurrentHashMap();
private DataSourceHolder dataSourceHolder;
public DaoInvocationHandler(DataSourceHolder dataSourceHolder) {
this.dataSourceHolder = dataSourceHolder;
}
//对应于Dao接口里的函数
//将每一个函数映射为一个SqlExecutor
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!sqlExecutorMap.containsKey(method)) {
synchronized (method) {
if (!sqlExecutorMap.containsKey(method)) {
SqlExecutor sqlExecutor = new SqlExecutor.Builder(method, dataSourceHolder.getLightTemplate()).build();
sqlExecutorMap.put(method, sqlExecutor);
}
}
}
return sqlExecutorMap.get(method).execute(args);
}
}
我们需要对default方法做特殊处理,搜索了一下stackoverflow
里面提供了一种解决方式:
Object result = MethodHandles.lookup()
.in(method.getDeclaringClass())
.unreflectSpecial(method,method.getDeclaringClass())
.bindTo(target)
.invokeWithArguments();
但是在使用时,报错如下:
Caused by: java.lang.IllegalAccessException: no private access for invokespecial
又尝试了几次,发现这种方式的改进版:
Constructor constructor = MethodHandles.Lookup.class
.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
Class> declaringClass = method.getDeclaringClass();
int allModes = MethodHandles.Lookup.PUBLIC | MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED | MethodHandles.Lookup.PACKAGE;
return constructor.newInstance(declaringClass, allModes)
.unreflectSpecial(method, declaringClass)
.bindTo(proxy)
.invokeWithArguments(args);
通过设置constructor.setAccessible(true);来解决access权限问题。目前来看,问题基本解决。最终的invocationHandler代码如下:
public class DaoInvocationHandler implements InvocationHandler {
private Map sqlExecutorMap = new ConcurrentHashMap();
private DataSourceHolder dataSourceHolder;
public DaoInvocationHandler(DataSourceHolder dataSourceHolder) {
this.dataSourceHolder = dataSourceHolder;
}
//对应于Dao接口里的函数
//将每一个函数映射为一个SqlExecutor
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//default方法不重写
if (method.isDefault()) {
Constructor constructor = MethodHandles.Lookup.class
.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
Class> declaringClass = method.getDeclaringClass();
int allModes = MethodHandles.Lookup.PUBLIC | MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED | MethodHandles.Lookup.PACKAGE;
return constructor.newInstance(declaringClass, allModes)
.unreflectSpecial(method, declaringClass)
.bindTo(proxy)
.invokeWithArguments(args);
} else if (!sqlExecutorMap.containsKey(method)) {
synchronized (method) {
if (!sqlExecutorMap.containsKey(method)) {
SqlExecutor sqlExecutor = new SqlExecutor.Builder(method, dataSourceHolder.getLightTemplate()).build();
sqlExecutorMap.put(method, sqlExecutor);
}
}
}
return sqlExecutorMap.get(method).execute(args);
}
}
虽然解决了问题,但还是觉得java 8应该在method里添加针对interface default方法的直接调用方式,这样绕一大圈的解决方式显然不够优雅。
只能期待reflect api下个版本的修改了。
java接口中的default_java8 通过反射执行接口的default方法相关推荐
- java 拦截器顺序_Springmvc拦截器执行顺序及各方法作用详解
实现HandlerInterceptor接口或者继承HandlerInterceptor的子类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInt ...
- 通过反射执行get、set方法
Class clazz = sourceObj.getClass(); 1.获取所有属性 BeanInfo beanInfo = Introspector.getBeanInfo(clazz); Pr ...
- Java default 方法
Default 方法 前言:当我在用Spring boot框架开发项目中配置Webconfig类时,该类实现了WebMvcConfigurerAdapter抽象类.但是IDE提示WebMvcConfi ...
- java 反射执行语句_JAVA反射机制
JAVA反射机制定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的 ...
- java调用一个方法后怎么继续执行不等待该方法的返回_Java面试题大全2020版(二)...
今天给大家推送第二部分,主要的大块内容分为:多线程.反射.对象拷贝.三大块内容中涉及到的考点如下: 三.多线程 35. 并行和并发有什么区别? 并行是指两个或者多个事件在同一时刻发生:而并发是指两个或 ...
- 【Android NDK 开发】JNI 线程 ( JNI 线程创建 | 线程执行函数 | 非 JNI 方法获取 JNIEnv 与 Java 对象 | 线程获取 JNIEnv | 全局变量设置 )
文章目录 I . JNI 线程创建 II . 线程执行函数 III . 线程方法获取 Java 对象 IV . 线程方法获取 JNIEnv V . JNI 线程 完整代码示例 I . JNI 线程创建 ...
- 深入理解Java类型信息(Class对象)与反射机制
关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java并发之synchronize ...
- java display.getdefault()_java基础(十一 )-----反射——Java高级开发必须懂的
本文我们通过一个实际的例子来演示反射在编程中的应用,可能之前大家对反射的学习,仅仅是停留在概念层面,不知道反射究竟应用在哪,所以是一头雾水.相信通过这篇教程,会让你对反射有一个更深层次的认知. 概念 ...
- Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多.要怎么理解以上这句话,请看下文. 一.反射 反射机制是 Ja ...
最新文章
- 《2021全球脑科学发展报告》发布
- git-svn:通过git来管理svn代码
- 查看临界区等待线程数量
- 老男孩教育Python 9期第一课练习题答案
- 【NLP】NLP提效,除了选择合适的模型,就是数据增强了
- Html table 实现Excel多格粘贴
- 为什么一直没有意识到自己还是面向过程编程
- 2018-3-28Linux系统管理(16)计算机网络基础
- Java工程师必备技能
- web-java-Java Concurrency Utilities
- 自定义数字格式字符串_部分分隔符和条件格式
- 练习题︱基于今日头条开源数据(二)——两款Apriori算法实践
- 解读【ICLR2020】多伦多大学:基于策略网络的探索模型规划
- ASP.NET profile之 找不到存储过程'dbo.aspnet_CheckSchemaVersion'
- shell倒数第三位增加字符_shell中常用的变量处理、字符串操作(之三)
- humid vs wet vs moist
- Redis的DMS管理工具treeNms
- 【1】EFR32配置433Mhz(可通信CC1101)——EFR32 项目例程打开和烧录
- 在格式化字符串的边缘试探
- php 多个一维数组合拼成二维数组的方法
热门文章
- Leetcode-Pascal's Triangle
- 从0开始学Swift笔记整理(五)
- [PHP] - Laravel - CSRF token禁用方法与排除验证csrf_token的url设置
- 将php分页类YII绑定框架,就需要改变风格的基础
- x86_64的debian(wheezy)下使用qemu和busybox运行linux
- python open w_python-文件操作示例
- Ubuntu18.04修改主机名和用户名
- Linux基于v4l2的视频采集(可用)
- 显示编译代码时长的demo
- C++之判断当前是debug还是realease