動态代理手動實作Spring AOP的基本功能:
這裡使用内部類實作, 實際上可能使用反射實作會更好一些, 沒仔細研究.
package com.frog.utils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtils {
private final Class<?> clazz;
private Method method;
public void setMethod(String methodName, Class<?>... parameterTypes) throws Exception {
method = clazz.getMethod(methodName, parameterTypes);
}
public ProxyUtils(Class<?> clazz) {
this.clazz = clazz;
}
public Object getProxy(){
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new TempClass());
}
private boolean isSameMethod(Method method1, Method method2){
if(method1.getName().equals(method2.getName())){
if (!method1.getReturnType().equals(method2.getReturnType()))
return false;
Class<?>[] params1 = method1.getParameterTypes();
Class<?>[] params2 = method2.getParameterTypes();
if (params1.length == params2.length) {
for (int i = ; i < params1.length; i++) {
if (params1[i] != params2[i])
return false;
}
return true;
}
}
return false;
}
private class TempClass implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
if(ProxyUtils.this.method != null && !isSameMethod(ProxyUtils.this.method, method)) {
return method.invoke(clazz.newInstance(), args);
}
Object result = null;
boolean isNormal = true;
try{
ProceedingJoinPoint joinPoint = new ProceedingJoinPointImpl(method, args);
if(around != null){
result = around.callBack(joinPoint);
}else{
joinPoint.proceed();
}
}catch(Throwable t){
isNormal = false;
t.printStackTrace();
return null;
}finally{
if(after != null) after.callBack();
if(!isNormal && afterThrowing != null) afterThrowing.callBack();
}
if(afterReturning != null) afterReturning.callBack();
return result;
}
}
public interface ProceedingJoinPoint{
public Object proceed() throws Throwable;
}
private class ProceedingJoinPointImpl implements ProceedingJoinPoint{
private Method method;
private Object[] args;
public ProceedingJoinPointImpl(Method method, Object... args){
this.method = method;
this.args = args;
}
public Object proceed() throws Throwable{
if(before != null) before.callBack();
return method.invoke(clazz.newInstance(), args);
}
}
private AroundHandler around;
private AfterReturningHandler afterReturning;
private AfterThrowingHandler afterThrowing;
private BeforeHandler before;
private AfterHandler after;
public void setAroundAdvice(AroundHandler ah){
around = ah;
}
public void setBeforeAdvice(BeforeHandler bmh){
before = bmh;
}
public void setAfterThrowingAdvice(AfterThrowingHandler ath){
afterThrowing = ath;
}
public void setAfterAdvice(AfterHandler amh){
after = amh;
}
public void setAfterReturning(AfterReturningHandler arh){
afterReturning = arh;
}
public interface AroundHandler{
public abstract Object callBack(ProceedingJoinPoint joinPoint) throws Throwable;
}
public interface AfterReturningHandler{
public abstract void callBack();
}
public interface AfterThrowingHandler{
public abstract void callBack();
}
public interface BeforeHandler{
public abstract void callBack();
}
public interface AfterHandler{
public abstract void callBack();
}
}