Mybatis可以通过@Dao
的注解直接把接口的实现对象给取出,大家都知道,接口是不可实例化的,也就是不能创建对象,但是我们只声明了接口,那么这个实例是怎么来的呢?MyBatis使用了动态代理,真正的对象是增强过的InvocationHandler
package java.lang.reflect.Proxy
源码:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
通过getAnnotation
方法取出目标注解Dao
,在InvocationHandler
接口的实现中,对标明了@Dao
的Mapper
方法进行增强
---测试Mapper类如下:
package zxj.proxy;
public interface Animal {
@Dao("走")
public void run();
@Dao("吃")
public void eat();
@Dao("叫")
public String call();
}
---代理实现如下:
InvocationHandler handler = new InvocationHandler() {
/**
* 代理对象 执行方法 方法参数
*/
@Override
public Object invoke(Object handler, Method method, Object[] params) throws Throwable {
Dao dao = method.getAnnotation(Dao.class);
if (null != dao) {
String value = dao.value();
System.out.println(value);
} else {
System.out.println("null");
}
Class<?> returnType = method.getReturnType();
System.out.println(returnType.getName());
return null;
}
};
@SuppressWarnings("unchecked")
Class<Animal> cl = (Class<Animal>) Class.forName("zxj.proxy.Animal");
Class<?>[] cc = { cl };
Object instance = Proxy.newProxyInstance(Animal.class.getClassLoader(), cc, handler);
System.out.println(instance.getClass().getName());
Animal an = (Animal) instance;
an.run();
an.call();
an.eat();