实现步骤
(1)定义一个接口,代理的是接口(多态),不是具体的实现类;
(2)定义处理类(实现InvocationHandler接口),重写invoke方法,由要代理接口的实现类来实例化处理类;
(3)定义代理类Proxy,调用方法。
创建接口:此情况代理的是接口,如目标类没有实现接口用CGLIB动态代理目标类.不妨回顾一下mybatis的实现原理,在项目开发中的UserMapper接口和与之对应的UserMapper.xml
public interface EatInterface {
public String eat(String name, int num) ;
}
接口实现类:
public class CatEat implements EatInterface {
@Override
public String eat(String name, int num) {
System.out.println("cat eat fish");
return name+num;
}
//此方法不是接口的方法,不能通过代理调用
public String eat2() {
System.out.println("cat eat fish");
return "hello world";
}
}
定义处理类:
public class DynamicSubject implements InvocationHandler {
public Object obj;
public DynamicSubject(Object obj){
this.obj =obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("subject--start");
//invoke方法传入的是对象实例和方法参数
Object object =method.invoke(obj,args);
System.out.println("subject--end");
return object;
}
}
定义代理类:
//用泛型更灵活 若使用Generic<T extends EatInterface>可限制只能代理此接口
public class Generic<T > {
T field;
public T getField() {
return field;
}
public void setField(T field) {
this.field = field;
}
public Object doInvoke(String methodName,Object[] args){
//实例化处理器
DynamicSubject iv = new DynamicSubject(this.field);
//获取代理对象
T porxy = (T) Proxy.newProxyInstance(iv.getClass().getClassLoader(),this.field.getClass().getInterfaces(),iv);
Field[] fields = porxy.getClass().getFields();
for(Field field :fields){
System.out.println("方法:"+field.getName());
}
System.out.println("父类是:"+porxy.getClass().getSuperclass());
System.out.print("实现的接口是:");
Class<?>[] interfaces = porxy.getClass().getInterfaces();
for(Class<?> interfaceItem :interfaces){
System.out.println(interfaceItem.getName());
}
Method[] methods = porxy.getClass().getMethods();
for(Method method :methods){
System.out.println("方法:"+method.getName());
//获取方法可用porxy.getClass().getMethod(name,parameterTypes)
if(methodName.equals(method.getName())){
try {
//此处直接返回
return method.invoke(porxy,args);
//method.invoke(porxy,args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
return null;
}
//测试
public static void main(String[] args) {
//对象可由第三方传来的classname来生成{classname,method,params}
CatEat p = new CatEat();
Generic<CatEat> t = new Generic<CatEat>();
t.setField(p);
Object ret = t.doInvoke("eat",new Object[]{"Fish",3});
//无法调用实现类自定义的方法 再次强调是代理接口
//Object ret = t.doInvoke("eat2",new Object[]{"hello",3});
System.out.println((String)ret);
}
}