💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
~~~ /** * Copyright 2009-2020 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 * * http://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 org.apache.ibatis.binding; 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; import org.apache.ibatis.reflection.ExceptionUtil; import org.apache.ibatis.session.SqlSession; /** * @author Clinton Begin * @author Eduardo Macarron */ public class MapperProxy<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; //会话相关 private final SqlSession sqlSession; //mapper接口 private final Class<T> mapperInterface; //将方法和方法执行器做映射 private final Map<Method, MapperMethodInvoker> methodCache; public MapperProxy(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); } else { return cachedInvoker(method).invoke(proxy, method, args, sqlSession); } } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } //选择方法执行器 private MapperMethodInvoker cachedInvoker(Method method) throws Throwable { try { return methodCache.computeIfAbsent(method, m -> { if (m.isDefault()) { try { if (privateLookupInMethod == null) { return new DefaultMethodInvoker(getMethodHandleJava8(method)); } else { return new DefaultMethodInvoker(getMethodHandleJava9(method)); } } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e) { throw new RuntimeException(e); } } else { return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration())); } }); } catch (RuntimeException re) { Throwable cause = re.getCause(); throw cause == null ? re : cause; } } //获取java9的方法执行器 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); } //获取java8的方法执行器 private MethodHandle getMethodHandleJava8(Method method) throws IllegalAccessException, InstantiationException, InvocationTargetException { final Class<?> declaringClass = method.getDeclaringClass(); return lookupConstructor.newInstance(declaringClass, ALLOWED_MODES).unreflectSpecial(method, declaringClass); } //Mapper方法执行接口 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) { super(); this.mapperMethod = mapperMethod; } @Override public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable { return mapperMethod.execute(sqlSession, args); } } //default方法的执行器 private static class DefaultMethodInvoker implements MapperMethodInvoker { private final MethodHandle methodHandle; public DefaultMethodInvoker(MethodHandle methodHandle) { super(); this.methodHandle = methodHandle; } @Override public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable { return methodHandle.bindTo(proxy).invokeWithArguments(args); } } } ~~~