在项目中使用了百度语音功能打开sdk发现了一个面向切面的支持包(aop)。由于代码被混淆过看起来着实痛苦,通过大胆猜测和验证终于将代码复原并为我所用。aop的代码思路是通过反射执行代理对象已注册的方法,在方法前遍历所有的拦截器,通过验证拦截器的返回值判断是否执行次方法,如果执行在方法后遍历所有的拦截器。在执行网络请求之前我们要判断网络是否可用、 是否重复请求、弹出加载框、打印参数结果日志,而在这里我将它们定义为4种拦截器。
1. NewWorkInterceptor 网络拦截器
2. RepeatInterceptor 重复拦截器
3. ProgressDialogInterceptor 对话框拦截器(不拦截,只加载)
4. HttpLogInterceptor 日志拦截器(不拦截,值打印参数、结果、耗时)
代码:先贴aop代码
过滤器
public interface IInterceptor {
/**
* 方法执行前
*
* @param proxy
* @param method
* @param args
* @return
*/
Object before(Object proxy, Method method, Object[] args);
/**
* 方法执行后
*
* @param proxy
* @param method
* @param args
* @param methodReturn
* @return
*/
Object after(Object proxy, Method method, Object[] args, Object methodReturn);
}
拦截器处理者
public interface IInterceptorHandler extends InvocationHandler {
/**
* 注册多个方法
*/
void registerMethods();
/**
* 注册一个方法
* @param methodName
*/
void registerMethod(String methodName);
/**
* 注销一个方法
* @param methodName
*/
void unregisterMethod(String methodName);
/**
* 是否拦截
* @param methodName
* @return
*/
boolean canIntercept(String methodName);
/**
* 绑定
* @param proxied
* @param interceptors
* @return
*/
Object bind(Object proxied, List<IInterceptor> interceptors);
}
代理工厂
public interface IProxyFactory<T> {
/**
* 创建被代理对象
*
* @return
*/
T createProxied();
/**
* 拦截器处理对象
*
* @return
*/
IInterceptorHandler createInterceptorHandler();
/**
* 创建拦截器集合
*
* @return
*/
List<IInterceptor> createInterceptors();
/**
* 执行代理
*
* @return
*/
T makeProxy();
}
抽象拦截器
public abstract class AInterceptor implements IInterceptor {
public static final String TAG = "HttpLog";
protected List<String> methods = new ArrayList();
public AInterceptor() {
this.addMetodName();
}
@Override
public Object before(Object proxied, Method method, Object[] args) {
return this.isAdd(method.getName()) ? this.interceptor(proxied, method, args) : AInterceptorHandler.DEFAULT;
}
@Override
public Object after(Object proxied, Method method, Object[] args, Object methodReturn) {
return AInterceptorHandler.DEFAULT;
}
private boolean isAdd(String methodName) {
return methods.contains(methodName);
}
protected abstract void addMetodName();
protected abstract Object interceptor(Object proxied, Method method, Object[] args);
}
抽象拦截器处理者
public abstract class AInterceptorHandler implements IInterceptorHandler {
public static final Object DEFAULT = Integer.valueOf(0);
public static final Object END = Integer.valueOf(1);
protected List<IInterceptor> interceptors;
protected Object proxied;
protected List<String> methodNames = new ArrayList();
public AInterceptorHandler() {
}
@Override
public Object bind(Object proxied, List<IInterceptor> interceptors) {
this.proxied = proxied;
this.interceptors = interceptors;
Class clazz = this.proxied.getClass();
Object proxy = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
Log.d("AInterceptorHandler", "proxy=" + proxy);
return proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
boolean canIntercept = this.canIntercept(methodName);
if (canIntercept) {
Object result = null;
Object beforeResult = this.before(this.proxied, method, args);
if (beforeResult.equals(END)) {
return result;
} else {
result = method.invoke(this.proxied, args);
Object afterResult = this.after(this.proxied, method, args, result);
Log.d("AInterceptorHandler", "afterResult=" + afterResult);
return result;
}
} else {
return method.invoke(this.proxied, args);
}
}
@Override
public void registerMethod(String methodName) {
if (methodName != null) {
this.methodNames.add(methodName);
}
}
@Override
public void unregisterMethod(String methodName) {
if (methodName != null) {
this.methodNames.remove(methodName);
}
}
@Override
public boolean canIntercept(String methodName) {
return this.methodNames.contains(methodName);
}
protected Object before(Object proxy, Method method, Object[] args) {
Object result = DEFAULT;
int size = this.interceptors.size();
for (int i = 0; i < size; ++i) {
result = this.interceptors.get(i).before(proxy, method, args);
if (result.equals(END)) {
return result;
}
}
return result;
}
protected Object after(Object proxy, Method method, Object[] args, Object methodReturn) {
Object result = DEFAULT;
int size = this.interceptors.size();
for (int i = size - 1; i >= 0; --i) {
result = this.interceptors.get(i).after(proxy, method, args, methodReturn);
}
return result;
}
}
下面是网络请求部分
网络拦截器
public class NetWorkInterceptor extends AInterceptor {
@Override
protected void addMetodName() {
methods.add("requestPost");
methods.add("requestGet");
}
@Override
protected Object interceptor(Object proxied, Method method, Object[] args) {
IDataProvider dataProvider = DataProviderManager.getDataProvider();
if (dataProvider.getNetType() == NetState.NETWORN_NONE) {
T.ToastShort("当前无网络,请检查网络设置");
return AInterceptorHandler.END;
}
return AInterceptorHandler.DEFAULT;
}
}
重复拦截器
public class RepeatInterceptor extends AInterceptor {
private List<String> urlList;
private boolean interceptor;
public RepeatInterceptor() {
urlList = Collections.synchronizedList(new ArrayList());
}
@Override
protected void addMetodName() {
methods.add("requestPost");
methods.add("requestGet");
}
@Override
public Object before(Object proxied, Method method, Object[] args) {
if (!Util.isEmpty(args)) {
String url = args[0].toString();
if (urlList.contains(url)) {
interceptor = true;
} else {
interceptor = false;
urlList.add(url);
}
}
return super.before(proxied, method, args);
}
@Override
protected Object interceptor(Object proxied, Method method, Object[] args) {
String url = args[0].toString();
if (interceptor) {
L.d(TAG, "过滤重复请求" + url);
return AInterceptorHandler.END;
}
return AInterceptorHandler.DEFAULT;
}
@Override
public Object after(Object proxied, Method method, Object[] args, Object methodReturn) {
if (!Util.isEmpty(args)) {
String url = args[0].toString();
urlList.remove(url);
}
return super.after(proxied, method, args, methodReturn);
}
}
对话框拦截器
public class ProgressDialogInterceptor extends AInterceptor {
private DialogHelper mDialogHelper;
private SimpleHttpCallback callback;
@Override
protected void addMetodName() {
methods.add("requestPost");
methods.add("requestGet");
}
@Override
protected Object interceptor(Object proxied, Method method, Object[] args) {
return AInterceptorHandler.DEFAULT;//不做拦截
}
@Override
public Object before(Object proxied, Method method, Object[] args) {
if (mDialogHelper != null) {
mDialogHelper.showLoadingProgressDialog();
}
if (args[2] != null && args[2] instanceof SimpleHttpCallback) {
callback = (SimpleHttpCallback) args[2];
}
return super.before(proxied, method, args);
}
@Override
public Object after(Object proxied, Method method, Object[] args, Object methodReturn) {
if (callback != null) {
callback.addResult(new SimpleHttpCallback.IResult() {
@Override
public void result(String data) {
if (mDialogHelper != null) {
mDialogHelper.dismissProgressDialog();
}
}
});
} else {
if (mDialogHelper != null) {
mDialogHelper.dismissProgressDialog();
}
}
return super.after(proxied, method, args, methodReturn);
}
public void setDialogHelper(DialogHelper dialogHelper) {
this.mDialogHelper = dialogHelper;
}
}
日志拦截器
public class HttpLogInterceptor extends AInterceptor {
/**
* 开始时间
*/
private long beginTime;
private SimpleHttpCallback callback;
@Override
protected void addMetodName() {
methods.add("requestPost");
methods.add("requestGet");
}
@Override
protected Object interceptor(Object proxied, Method method, Object[] args) {
return AInterceptorHandler.DEFAULT; //不做拦截
}
@Override
public Object before(Object proxied, Method method, Object[] args) {
beginTime = System.currentTimeMillis();
if (!Util.isEmpty(args)) {
//打印url
L.d(TAG, "url:" + args[0].toString() + "\n");
//打印参数
if (args[1] != null) {
Map<String, String> map = (Map) args[1];
for (Map.Entry<String, String> entry : map.entrySet()) {
L.d(TAG, " "+entry.getKey() + " : " + entry.getValue());
}
}
//请求回调
if (args[2] != null && args[2] instanceof SimpleHttpCallback) {
callback = (SimpleHttpCallback) args[2];
}
}
return super.before(proxied, method, args);
}
@Override
public Object after(Object proxied, Method method, Object[] args, Object methodReturn) {
if (callback != null) {
callback.addResult(new SimpleHttpCallback.IResult() {
@Override
public void result(String data) {
L.d(TAG, "result:" + data);
L.d(TAG, " 网络耗时 : " + (System.currentTimeMillis() - beginTime) / 1000f + " 秒 ");
}
});
}
return super.after(proxied, method, args, methodReturn);
}
}
拦截器处理者
public class HttpHandler extends AInterceptorHandler {
@Override
public void registerMethods() {
methodNames.add("requestPost");
methodNames.add("requestGet");
}
}
拦截器工厂
public class HttpFactory extends AProxyFactory<AiJuHttp> {
private ArrayList interceptors = new ArrayList();
private HttpHandler mHttpHandler;
private ProgressDialogInterceptor mDialogInterceptor;
private static volatile HttpFactory instance;
public static HttpFactory getInstance() {
if (instance == null) {
synchronized (HttpFactory.class) {
if (instance == null) {
instance = new HttpFactory();
}
}
}
return instance;
}
private HttpFactory() {
mHttpHandler = new HttpHandler();
mHttpHandler.registerMethods();
mDialogInterceptor = new ProgressDialogInterceptor();
//网络拦截
interceptors.add(new NetWorkInterceptor());
//重复请求拦截
interceptors.add(new RepeatInterceptor());
//不拦截,加入加载对话框
interceptors.add(mDialogInterceptor);
//不拦截,加入打印参数、返回值、耗时日志
interceptors.add(new HttpLogInterceptor());
}
public void setDialogHelper(DialogHelper dialogHelper) {
if (mDialogInterceptor != null) {
mDialogInterceptor.setDialogHelper(dialogHelper);
}
}
@Override
public AiJuHttp createProxied() {
return AiJuHttpProxy.getInstance();
}
@Override
public IInterceptorHandler createInterceptorHandler() {
return mHttpHandler;
}
@Override
public List<IInterceptor> createInterceptors() {
return interceptors;
}
}
这里有很多项目封装的类,功能大家都知道的代码就不贴出了。
DateProviderManager 项目基础信息
L 日志打印工具类
T 吐司工具类
DialogHelper 对话框工具类
AjJuHttpProxy 网络请求代理类隔离第三组件
这里贴出日志打印结果:1.url 2. 参数 3. 结果 4. 网络耗时