Mybatis可以通过@Dao的注解直接把接口的实现对象给取出,大家都知道,接口是不可实例化的,也就是不能创建对象,但是我们只声明了接口,那么这个实例是怎么来的呢?MyBatis使用了动态代理,真正的对象是增强过的InvocationHandler
    package java.lang.reflect.Proxy源码:

    1. public static Object newProxyInstance(ClassLoader loader,
    2. Class<?>[] interfaces,
    3. InvocationHandler h)

    通过getAnnotation方法取出目标注解Dao,在InvocationHandler接口的实现中,对标明了@DaoMapper方法进行增强

    1. ---测试Mapper类如下:
    2. package zxj.proxy;
    3. public interface Animal {
    4. @Dao("走")
    5. public void run();
    6. @Dao("吃")
    7. public void eat();
    8. @Dao("叫")
    9. public String call();
    10. }
    11. ---代理实现如下:
    12. InvocationHandler handler = new InvocationHandler() {
    13. /**
    14. * 代理对象 执行方法 方法参数
    15. */
    16. @Override
    17. public Object invoke(Object handler, Method method, Object[] params) throws Throwable {
    18. Dao dao = method.getAnnotation(Dao.class);
    19. if (null != dao) {
    20. String value = dao.value();
    21. System.out.println(value);
    22. } else {
    23. System.out.println("null");
    24. }
    25. Class<?> returnType = method.getReturnType();
    26. System.out.println(returnType.getName());
    27. return null;
    28. }
    29. };
    30. @SuppressWarnings("unchecked")    
    31. Class<Animal> cl = (Class<Animal>) Class.forName("zxj.proxy.Animal");
    32. Class<?>[] cc = { cl };
    33. Object instance = Proxy.newProxyInstance(Animal.class.getClassLoader(), cc, handler);
    34. System.out.println(instance.getClass().getName());
    35. Animal an = (Animal) instance;
    36. an.run();
    37. an.call();
    38. an.eat();