最近看JPA,一直纠结于怎么根据Java接口的方法名称、参数和返回值类型动态的实现接口方法的逻辑,于是看了一下JAVA动态代理的实现过程,对Spring动态实现接口方法逻辑进行了模拟。
场景:
1.按照命名规则对JAVA接口方法进行命名;在解析时能够根据方法名称分析出要执行怎样的操作。
2.方法参数。基于接口或泛型命名的接口参数,能够根据接口或对泛型对象的反射获取参数值。
3.方法返回值。方法返回值的处理与方法参数的处理过程类似。
4.JAVA提供基于接口的动态代理,需要的类或接口为:Proxy、InvocationHandler(接口)。具体的代理对象必须实现InvocationHandler接口,在方法invoke方法中根据方法名称、参数和返回值分析要执行的操作,并实现相应的代码逻辑。
5.通过Proxy.newProxyInstance方法关联接口和代理对象,返回接口的实现对象。直接使用接口执行相应的操作。newProxyInstance需要的参数为类装载器、代理接口数组和执行代理逻辑的代理对象,完全可以实现基于接口的代理,不需要接口的实现类。
例子:
接口Hello:
package example;
/**
* Hello接口中有两个多态型式的方法
*/
public interface Hello {
public String sayHello(String name) ;
public String sayHello(String name,int age) ;
}
代理对象ProxyTarget:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTarget implements InvocationHandler {
/**
* 根据方法名称、参数和返回值类型动态实现方法逻辑<br>
* 根据方法的名称实现拦截
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("method before...");
System.out.print("方法->"+method.getReturnType().getName()+" "+method.getName()+"(");
for (int i = 0; i < method.getParameterTypes().length; i++) {
System.out.print(method.getParameterTypes()[i].getName());
if(i<method.getParameterTypes().length-1){
System.out.print(",");
}
}
System.out.println(")");
System.out.println("根据方法名称、参数和返回值分析要执行的操作,并实现代码逻辑");
System.out.println("method after...");
return "" ;
}
}
测试main代码:
public static void main(String[] args) {
ProxyTarget proxyTarget = new ProxyTarget() ;
Hello hello = (Hello)Proxy.newProxyInstance(proxyTarget.getClass().getClassLoader(),new Class[]{Hello.class} , proxyTarget) ;
hello.sayHello("lp") ;
hello.sayHello("lp",27) ;
}
以上动态代理Demo是对接口方法逻辑的动态实现,不需要方法的实现对象。将接口实现对象加入代理对象可以实现日志拦截、事务代理等AOP操作。