动态代理之投鞭断流

还是直接看代码实现吧

首先定义一个实体

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接口

public interface UserMapper {
    User getUserById(Integer id);
}

然后自定义一个invacationHandle

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());
}

输出结果

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

猜你喜欢

转载自my.oschina.net/u/3737136/blog/1786175