仍是直接看代碼實現吧sql
首先定義一個實體mybatis
public class User { private Integer id; private String name; private int age; public User(Integer id, String name, int age) { this.id = id; this.name = name; this.age = age; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
在定義一個mapper接口app
public interface UserMapper { User getUserById(Integer id); }
而後自定義一個invacationHandleide
public class MapperProxy implements InvocationHandler { /** * 利用Proxy.newProxyInstance 獲取代理類 * @param clz 目標接口 * @param <T> * @return */ @SuppressWarnings("unchecked") public <T> T newInstance(Class<T> clz) { return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] { clz }, this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //判斷method是不是Object類中定義的方法 //如 hashCode()、toString()、equals() //若是是則將target 指向 this //若是直接調用 method.invoke 會報空指針錯誤 if (Object.class.equals(method.getDeclaringClass())) { try { return method.invoke(this, args); } catch (Throwable t) { } } // 投鞭斷流 // mybatis mapper底層實現原理 return findUserById((Integer) args[0]); } private User findUserById(Integer id) { return new User(id, "zhangsan", 18); } }
測試測試
public static void main(String[] args) { MapperProxy proxy = new MapperProxy(); //獲取代理類 UserMapper mapper = proxy.newInstance(UserMapper.class); User user = mapper.getUserById(1001); System.out.println("ID:" + user.getId()); System.out.println("Name:" + user.getName()); System.out.println("Age:" + user.getAge()); System.out.println(mapper.toString()); }
輸出結果this
mybatis底層源碼就是這麼實現的,看看mybatis是怎麼寫的吧代理
@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 if (isDefaultMethod(method)) { return invokeDefaultMethod(proxy, method, args); } } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } final MapperMethod mapperMethod = cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); }
是否是很像 除了最後的return指針