動態代理之投鞭斷流

仍是直接看代碼實現吧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指針

相關文章
相關標籤/搜索