mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-06 16:48:24 +08:00
refactor: performance optimization
This commit is contained in:
parent
adb43c6c47
commit
eb663b3518
@ -279,7 +279,7 @@ public class GeneratorTest {
|
||||
generator.generate();
|
||||
}
|
||||
|
||||
@Test
|
||||
// @Test
|
||||
public void testCodeGen5() {
|
||||
// 配置数据源
|
||||
HikariDataSource dataSource = new HikariDataSource();
|
||||
|
||||
@ -22,12 +22,15 @@ import com.mybatisflex.core.keygen.MultiEntityKeyGenerator;
|
||||
import com.mybatisflex.core.keygen.MultiRowKeyGenerator;
|
||||
import com.mybatisflex.core.keygen.MybatisKeyGeneratorUtil;
|
||||
import com.mybatisflex.core.keygen.RowKeyGenerator;
|
||||
import com.mybatisflex.core.mybatis.binding.FlexMapperRegistry;
|
||||
import com.mybatisflex.core.mybatis.executor.FlexBatchExecutor;
|
||||
import com.mybatisflex.core.mybatis.executor.FlexReuseExecutor;
|
||||
import com.mybatisflex.core.mybatis.executor.FlexSimpleExecutor;
|
||||
import com.mybatisflex.core.table.TableInfo;
|
||||
import com.mybatisflex.core.table.TableInfoFactory;
|
||||
import com.mybatisflex.core.util.MapUtil;
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
import org.apache.ibatis.binding.MapperRegistry;
|
||||
import org.apache.ibatis.executor.CachingExecutor;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.executor.keygen.KeyGenerator;
|
||||
@ -42,10 +45,8 @@ import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.ResultMap;
|
||||
import org.apache.ibatis.session.*;
|
||||
import org.apache.ibatis.transaction.Transaction;
|
||||
import com.mybatisflex.core.util.MapUtil;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -59,6 +60,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
public class FlexConfiguration extends Configuration {
|
||||
|
||||
private static final Map<String, MappedStatement> dynamicMappedStatementCache = new ConcurrentHashMap<>();
|
||||
private final MapperRegistry mapperRegistry = new FlexMapperRegistry(this);
|
||||
|
||||
public FlexConfiguration() {
|
||||
setObjectWrapperFactory(new FlexWrapperFactory());
|
||||
@ -345,17 +347,35 @@ public class FlexConfiguration extends Configuration {
|
||||
|
||||
//不支持泛型类添加
|
||||
if (!isGenericInterface) {
|
||||
super.addMapper(type);
|
||||
mapperRegistry.addMapper(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
|
||||
T mapper = super.getMapper(type, sqlSession);
|
||||
return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}
|
||||
, new MapperInvocationHandler(mapper, environment.getDataSource()));
|
||||
// @SuppressWarnings("unchecked")
|
||||
// @Override
|
||||
// public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
|
||||
// T mapper = super.getMapper(type, sqlSession);
|
||||
// return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}
|
||||
// , new MapperInvocationHandler(mapper, environment.getDataSource()));
|
||||
// }
|
||||
|
||||
|
||||
public void addMappers(String packageName, Class<?> superType) {
|
||||
mapperRegistry.addMappers(packageName, superType);
|
||||
}
|
||||
|
||||
public void addMappers(String packageName) {
|
||||
mapperRegistry.addMappers(packageName);
|
||||
}
|
||||
|
||||
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
|
||||
return mapperRegistry.getMapper(type, sqlSession);
|
||||
}
|
||||
|
||||
public boolean hasMapper(Class<?> type) {
|
||||
return mapperRegistry.hasMapper(type);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ public class MappedStatementTypes {
|
||||
private MappedStatementTypes() {
|
||||
}
|
||||
|
||||
private static ThreadLocal<Class<?>> currentTypeTL = new ThreadLocal<>();
|
||||
private static final ThreadLocal<Class<?>> currentTypeTL = new ThreadLocal<>();
|
||||
|
||||
public static void setCurrentType(Class<?> type) {
|
||||
currentTypeTL.set(type);
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mybatisflex.core.mybatis;
|
||||
package com.mybatisflex.core.mybatis.binding;
|
||||
|
||||
import com.mybatisflex.annotation.UseDataSource;
|
||||
import com.mybatisflex.core.FlexGlobalConfig;
|
||||
@ -21,38 +21,38 @@ import com.mybatisflex.core.datasource.DataSourceKey;
|
||||
import com.mybatisflex.core.datasource.FlexDataSource;
|
||||
import com.mybatisflex.core.dialect.DbType;
|
||||
import com.mybatisflex.core.dialect.DialectFactory;
|
||||
import com.mybatisflex.core.mybatis.FlexConfiguration;
|
||||
import com.mybatisflex.core.row.RowMapper;
|
||||
import com.mybatisflex.core.table.TableInfo;
|
||||
import com.mybatisflex.core.table.TableInfoFactory;
|
||||
import com.mybatisflex.core.util.MapUtil;
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
import org.apache.ibatis.reflection.ExceptionUtil;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author michael
|
||||
* @author norkts
|
||||
*/
|
||||
public class MapperInvocationHandler implements InvocationHandler {
|
||||
public class FlexMapperProxy<T> extends MybatisMapperProxy<T> {
|
||||
private static final String NULL_KEY = "@NK";
|
||||
private static final Map<Method, String> methodDsKeyCache = new ConcurrentHashMap<>();
|
||||
|
||||
private final Object mapper;
|
||||
private final FlexDataSource dataSource;
|
||||
|
||||
public MapperInvocationHandler(Object mapper, DataSource dataSource) {
|
||||
this.mapper = mapper;
|
||||
if (dataSource instanceof FlexDataSource) {
|
||||
this.dataSource = (FlexDataSource) dataSource;
|
||||
} else {
|
||||
this.dataSource = null;
|
||||
}
|
||||
public FlexMapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethodInvoker> methodCache,
|
||||
FlexConfiguration configuration) {
|
||||
super(sqlSession, mapperInterface, methodCache);
|
||||
this.dataSource = (FlexDataSource) configuration.getEnvironment().getDataSource();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (Object.class.equals(method.getDeclaringClass())) {
|
||||
return method.invoke(this, args);
|
||||
}
|
||||
|
||||
boolean needClearDsKey = false;
|
||||
boolean needClearDbType = false;
|
||||
try {
|
||||
@ -100,7 +100,8 @@ public class MapperInvocationHandler implements InvocationHandler {
|
||||
DialectFactory.setHintDbType(dbType);
|
||||
needClearDbType = true;
|
||||
}
|
||||
return method.invoke(mapper, args);
|
||||
// return method.invoke(mapper, args);
|
||||
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
|
||||
} catch (Throwable e) {
|
||||
throw ExceptionUtil.unwrapThrowable(e);
|
||||
} finally {
|
||||
@ -115,30 +116,33 @@ public class MapperInvocationHandler implements InvocationHandler {
|
||||
|
||||
|
||||
private static String getConfigDataSourceKey(Method method, Object proxy) {
|
||||
UseDataSource useDataSource = method.getAnnotation(UseDataSource.class);
|
||||
if (useDataSource != null && StringUtil.isNotBlank(useDataSource.value())) {
|
||||
return useDataSource.value();
|
||||
}
|
||||
|
||||
Class<?>[] interfaces = proxy.getClass().getInterfaces();
|
||||
for (Class<?> anInterface : interfaces) {
|
||||
UseDataSource annotation = anInterface.getAnnotation(UseDataSource.class);
|
||||
if (annotation != null) {
|
||||
return annotation.value();
|
||||
String result = MapUtil.computeIfAbsent(methodDsKeyCache, method, method1 -> {
|
||||
UseDataSource useDataSource = method1.getAnnotation(UseDataSource.class);
|
||||
if (useDataSource != null && StringUtil.isNotBlank(useDataSource.value())) {
|
||||
return useDataSource.value();
|
||||
}
|
||||
}
|
||||
|
||||
if (interfaces[0] != RowMapper.class) {
|
||||
TableInfo tableInfo = TableInfoFactory.ofMapperClass(interfaces[0]);
|
||||
if (tableInfo != null) {
|
||||
String dataSourceKey = tableInfo.getDataSource();
|
||||
if (StringUtil.isNotBlank(dataSourceKey)) {
|
||||
return dataSourceKey;
|
||||
Class<?>[] interfaces = proxy.getClass().getInterfaces();
|
||||
for (Class<?> anInterface : interfaces) {
|
||||
UseDataSource annotation = anInterface.getAnnotation(UseDataSource.class);
|
||||
if (annotation != null) {
|
||||
return annotation.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
if (interfaces[0] != RowMapper.class) {
|
||||
TableInfo tableInfo = TableInfoFactory.ofMapperClass(interfaces[0]);
|
||||
if (tableInfo != null) {
|
||||
String dataSourceKey = tableInfo.getDataSource();
|
||||
if (StringUtil.isNotBlank(dataSourceKey)) {
|
||||
return dataSourceKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL_KEY;
|
||||
});
|
||||
|
||||
return NULL_KEY.equals(result) ? null : result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2009-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mybatisflex.core.mybatis.binding;
|
||||
|
||||
import com.mybatisflex.core.mybatis.FlexConfiguration;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author Lasse Voss
|
||||
* @author Michael Yang
|
||||
*/
|
||||
public class FlexMapperProxyFactory<T> {
|
||||
|
||||
private final Class<T> mapperInterface;
|
||||
private final Map<Method, MybatisMapperProxy.MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();
|
||||
|
||||
public FlexMapperProxyFactory(Class<T> mapperInterface) {
|
||||
this.mapperInterface = mapperInterface;
|
||||
}
|
||||
|
||||
public Class<T> getMapperInterface() {
|
||||
return mapperInterface;
|
||||
}
|
||||
|
||||
public Map<Method, MybatisMapperProxy.MapperMethodInvoker> getMethodCache() {
|
||||
return methodCache;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T newInstance(FlexMapperProxy<T> mapperProxy) {
|
||||
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
|
||||
}
|
||||
|
||||
public T newInstance(SqlSession sqlSession, FlexConfiguration configuration) {
|
||||
final FlexMapperProxy<T> mapperProxy = new FlexMapperProxy<>(sqlSession, mapperInterface, methodCache, configuration);
|
||||
return newInstance(mapperProxy);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2009-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mybatisflex.core.mybatis.binding;
|
||||
|
||||
import com.mybatisflex.core.mybatis.FlexConfiguration;
|
||||
import org.apache.ibatis.binding.BindingException;
|
||||
import org.apache.ibatis.binding.MapperRegistry;
|
||||
import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder;
|
||||
import org.apache.ibatis.io.ResolverUtil;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class FlexMapperRegistry extends MapperRegistry {
|
||||
private final FlexConfiguration config;
|
||||
private final Map<Class<?>, FlexMapperProxyFactory<?>> knownMappers = new ConcurrentHashMap<>();
|
||||
|
||||
public FlexMapperRegistry(FlexConfiguration config) {
|
||||
super(config);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
|
||||
final FlexMapperProxyFactory<T> mapperProxyFactory = (FlexMapperProxyFactory<T>) knownMappers.get(type);
|
||||
if (mapperProxyFactory == null) {
|
||||
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
|
||||
}
|
||||
try {
|
||||
return mapperProxyFactory.newInstance(sqlSession, config);
|
||||
} catch (Exception e) {
|
||||
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> boolean hasMapper(Class<T> type) {
|
||||
return knownMappers.containsKey(type);
|
||||
}
|
||||
|
||||
public <T> void addMapper(Class<T> type) {
|
||||
if (type.isInterface()) {
|
||||
if (hasMapper(type)) {
|
||||
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
|
||||
}
|
||||
boolean loadCompleted = false;
|
||||
try {
|
||||
knownMappers.put(type, new FlexMapperProxyFactory<>(type));
|
||||
// It's important that the type is added before the parser is run
|
||||
// otherwise the binding may automatically be attempted by the
|
||||
// mapper parser. If the type is already known, it won't try.
|
||||
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
|
||||
parser.parse();
|
||||
loadCompleted = true;
|
||||
} finally {
|
||||
if (!loadCompleted) {
|
||||
knownMappers.remove(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mappers.
|
||||
*
|
||||
* @return the mappers
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public Collection<Class<?>> getMappers() {
|
||||
return Collections.unmodifiableCollection(knownMappers.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the mappers.
|
||||
*
|
||||
* @param packageName the package name
|
||||
* @param superType the super type
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public void addMappers(String packageName, Class<?> superType) {
|
||||
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
|
||||
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
|
||||
Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
|
||||
for (Class<?> mapperClass : mapperSet) {
|
||||
addMapper(mapperClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the mappers.
|
||||
*
|
||||
* @param packageName the package name
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public void addMappers(String packageName) {
|
||||
addMappers(packageName, Object.class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2009-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mybatisflex.core.mybatis.binding;
|
||||
|
||||
import com.mybatisflex.core.util.MapUtil;
|
||||
import org.apache.ibatis.binding.MapperMethod;
|
||||
import org.apache.ibatis.reflection.ExceptionUtil;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Clinton Begin
|
||||
* @author Eduardo Macarron
|
||||
* @author Michael Yang
|
||||
* <p>
|
||||
* 参考 MapperProxy<T> 并开放 MapperMethodInvoker,方便子类代理
|
||||
*/
|
||||
public class MybatisMapperProxy<T> implements InvocationHandler, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4724728412955527868L;
|
||||
private static final int ALLOWED_MODES = MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED
|
||||
| MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC;
|
||||
private static final Constructor<Lookup> lookupConstructor;
|
||||
private static final Method privateLookupInMethod;
|
||||
protected final SqlSession sqlSession;
|
||||
private final Class<T> mapperInterface;
|
||||
private final Map<Method, MapperMethodInvoker> methodCache;
|
||||
|
||||
public MybatisMapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethodInvoker> methodCache) {
|
||||
this.sqlSession = sqlSession;
|
||||
this.mapperInterface = mapperInterface;
|
||||
this.methodCache = methodCache;
|
||||
}
|
||||
|
||||
static {
|
||||
Method privateLookupIn;
|
||||
try {
|
||||
privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
privateLookupIn = null;
|
||||
}
|
||||
privateLookupInMethod = privateLookupIn;
|
||||
|
||||
Constructor<Lookup> lookup = null;
|
||||
if (privateLookupInMethod == null) {
|
||||
// JDK 1.8
|
||||
try {
|
||||
lookup = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
|
||||
lookup.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalStateException(
|
||||
"There is neither 'privateLookupIn(Class, Lookup)' nor 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.",
|
||||
e);
|
||||
} catch (Exception e) {
|
||||
lookup = null;
|
||||
}
|
||||
}
|
||||
lookupConstructor = lookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
try {
|
||||
if (Object.class.equals(method.getDeclaringClass())) {
|
||||
return method.invoke(this, args);
|
||||
}
|
||||
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
|
||||
} catch (Throwable t) {
|
||||
throw ExceptionUtil.unwrapThrowable(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
|
||||
try {
|
||||
return MapUtil.computeIfAbsent(methodCache, method, m -> {
|
||||
if (!m.isDefault()) {
|
||||
return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
|
||||
}
|
||||
try {
|
||||
if (privateLookupInMethod == null) {
|
||||
return new DefaultMethodInvoker(getMethodHandleJava8(method));
|
||||
}
|
||||
return new DefaultMethodInvoker(getMethodHandleJava9(method));
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
|
||||
| NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException re) {
|
||||
Throwable cause = re.getCause();
|
||||
throw cause == null ? re : cause;
|
||||
}
|
||||
}
|
||||
|
||||
private MethodHandle getMethodHandleJava9(Method method)
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
||||
final Class<?> declaringClass = method.getDeclaringClass();
|
||||
return ((Lookup) privateLookupInMethod.invoke(null, declaringClass, MethodHandles.lookup())).findSpecial(
|
||||
declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()),
|
||||
declaringClass);
|
||||
}
|
||||
|
||||
private MethodHandle getMethodHandleJava8(Method method)
|
||||
throws IllegalAccessException, InstantiationException, InvocationTargetException {
|
||||
final Class<?> declaringClass = method.getDeclaringClass();
|
||||
return lookupConstructor.newInstance(declaringClass, ALLOWED_MODES).unreflectSpecial(method, declaringClass);
|
||||
}
|
||||
|
||||
public interface MapperMethodInvoker {
|
||||
Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable;
|
||||
}
|
||||
|
||||
private static class PlainMethodInvoker implements MapperMethodInvoker {
|
||||
private final MapperMethod mapperMethod;
|
||||
|
||||
public PlainMethodInvoker(MapperMethod mapperMethod) {
|
||||
this.mapperMethod = mapperMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
|
||||
return mapperMethod.execute(sqlSession, args);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DefaultMethodInvoker implements MapperMethodInvoker {
|
||||
private final MethodHandle methodHandle;
|
||||
|
||||
public DefaultMethodInvoker(MethodHandle methodHandle) {
|
||||
this.methodHandle = methodHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
|
||||
return methodHandle.bindTo(proxy).invokeWithArguments(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user