proxy代理实现接口调用处理
我们知道,要调用接口必须要实例化才能调用。 那么我们能不能不实例化调用呢?像mybatis、hibernate那样定义一个接口就能注入调用。其实他们的底层实现就是用代理模式 proxy: 在不实例化的情况下调用接口(实际上代理实例化了)
首先定义一个注解用来区别
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Select {
String value() default "";
}
再编写一个调用接口
import java.util.Map;
public interface MyMapper {
@Select("select * from user where id=?")
Map select(Integer id);
}
然后定义代理调用处理类
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class MyInvocationHandler implements InvocationHandler, Serializable {
private Class<?> clazz;
public MyInvocationHandler(Class<?> clazz) {
this.clazz = clazz;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method exMethod = clazz.getMethod(method.getName(), getClassTypes(args));
if (args[0].getClass().isArray()) {
args = (Object[]) args[0];
if (args.length == 0)
args = null;
}
Select select = exMethod.getAnnotation(Select.class);
System.out.println("查询SQL:" + select.value());
System.out.println("参数: " + args[0]);
Class<?> returnType = getReturnType(exMethod);
System.out.println("接口需要返回的结果类型: " + returnType);
Map map = new HashMap();
map.put("result", "hello lingkang!");
System.out.println("假设在此执行SQL返回结果:");
return map;
}
public static Class<?> getReturnType(Method method) {
Type returnType = method.getGenericReturnType();
if (returnType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) returnType;
return (Class<?>) type.getActualTypeArguments()[0];
} else if ("void".equals(returnType.getTypeName())) {
return null;
}
return Map.class;
}
public static Class<?>[] getClassTypes(Object[] args) {
Class[] clazz = new Class[args.length];
for (int i = 0; i < args.length; i++)
clazz[i] = args[i].getClass();
return clazz;
}
}
调用这个代理处理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Demo01 {
public static void main(String[] args) {
MyMapper mapper = getMapper(MyMapper.class, new MyInvocationHandler(MyMapper.class));
System.out.println("调用结果:"+mapper.select(1));
}
public static <T> T getMapper(Class<T> clazz, InvocationHandler handler) {
return (T) Proxy.newProxyInstance(
clazz.getClassLoader(),
new Class[]{clazz},
handler);
}
}
结果:
|