AOP (Aspect Oriented Programming)面向切面编程
-----不修改源代码的情况下给程序动态统一添加功能.
比如说,一个方法作为"切入点","切面"类中可以提供拦截方法分别对"切入点"方法之前和之后进行拦截,即不修改源程序,动态添加功能.
本篇主要是模拟拦截器链的实现,相应实现的功能主要有:
1.用户可以选择代理模式(JDK代理或者CGLIB代理);
2.用户可以选择类和方法,进行拦截(通过映射关系);
3.对于一个类的同一个方法,是允许形成拦截器链的;
4.允许"前置拦截",“后置拦截”,“异常拦截”;
5.前置拦截是允许用户终止方法的执行,此时拦截器链应终止;
6.允许前置拦截更改方法参数,允许后置拦截更改方法的返回值;
7.拦截器的拦截功能由用户决定;
首先实现三个接口,前置,后置,异常拦截:
public interface IBefore {
boolean before();
}
public interface IAfter {
Object after(Object result);
}
public interface IThrowable {
void throwThrowable() throws Throwable;
}
这里我们将拦截器链又分为前置拦截器链和后置拦截器链,即由不同的拦截器构成的链表.
前置拦截器链的节点,即每一个前置拦截器:
public class BeforeIntercepterNode {
private IBefore before;
private BeforeIntercepterNode next;
BeforeIntercepterNode() {
}
BeforeIntercepterNode(IBefore before) {
this.before = before;
}
void setBefore(IBefore before) {
this.before = before;
}
void addNode(BeforeIntercepterNode node) {
if (next == null) {
next = node;
return;
}
next.addNode(node);
}
boolean doBefore() {
boolean ok = before.before();
if (!ok) {
return ok;
}
if (next != null) {
return next.doBefore();
}
return ok;
}
}
同理,生成后置拦截器链的节点,即后置拦截器:
public class AfterIntercepterNode {
private IAfter after;
private AfterIntercepterNode next;
AfterIntercepterNode() {
}
AfterIntercepterNode(IAfter after) {
this.after = after;
}
void setAfter(IAfter after) {
this.after = after;
}
void addNode(AfterIntercepterNode node) {
if (next == null) {
next = node;
return;
}
next.addNode(node);
}
Object doAfter(Object result) {
if (next == null) {
return after.after(result);
}
//这里采用“起泡”式执行后置拦截;
result = next.doAfter(result);
result = after.after(result);
return result;
}
}
这里说一下,doAfter()方法,采用"起泡"式进行后置拦截,下图可以更好的理解:
有了节点,就可以生成链表,前置拦截器链和后置拦截器链:
public class BeforeIntercepterLink {
private BeforeIntercepterNode head;
BeforeIntercepterLink() {
this.head = null;
}
void addIntercepter(IBefore before) {
BeforeIntercepterNode node = new BeforeIntercepterNode(before);
if (head == null) {
head = node;
}
head.addNode(node);
}
boolean before() {
if (head == null) {
return true;
}
return head.doBefore();
}
}
public class AfterIntercepterLink {
private AfterIntercepterNode head;
AfterIntercepterLink() {
this.head = null;
}
void addIntercepter(IAfter after) {
AfterIntercepterNode node = new AfterIntercepterNode(after);
if (head == null) {
head = node;
return;
}
head.addNode(node);
}
Object after(Object result) {
if (head == null) {
return result;
}
return head.doAfter(result);
}
}
由前置拦截器链和后置拦截器链构成拦截器链:
public class IntercepterLink {
private BeforeIntercepterLink beforeLink;
private AfterIntercepterLink afterLink;
private JoinPoint joinPoint;
IntercepterLink() {
this.beforeLink = null;
this.afterLink = null;
}
JoinPoint getJoinPoint() {
return joinPoint;
}
void setJoinPoint(JoinPoint joinPoint) {
this.joinPoint = joinPoint;
}
void addIntercepter(IBefore before) {
if (beforeLink == null) {
beforeLink = new BeforeIntercepterLink();
}
beforeLink.addIntercepter(before);
}
void addIntercepter(IAfter after) {
if (afterLink == null) {
afterLink = new AfterIntercepterLink();
}
afterLink.addIntercepter(after);
}
boolean before() {
if (beforeLink == null) {
return true;
}
return beforeLink.before();
}
Object after(Object result) {
if (afterLink == null) {
return result;
}
return afterLink.after(result);
}
}
同样,拦截器链中提供addIntercepter()方法和拦截方法before(),after(),可以发现从拦截器(节点)到前置或后置拦截器链再到拦截器链,这几个类中都相应存在增加拦截器和拦截方法,类似于一种由底向上的层次关系.
JoinPoint类是封装了被拦截方法相关的信息:
public class JoinPoint {
private Class<?> klass;
private Object object;
private Method method;
private Object[] paraValues;
private Class<?>[] paraTypes;
private ReturnValue returnValue;
这里的ReturnValue类是封装了被拦截方法的返回值及返回值类型:
public class ReturnValue {
private Class<?> returnType;
private Object value;
接下来就是对拦截方法的拦截功能,利用反射机制:
public class BeforeIntercepter implements IBefore {
private IntercepterLink intercepterLink;
private Method method;
private Object object;
public BeforeIntercepter() {
}
void setIntercepterLink(IntercepterLink intercepterLink) {
this.intercepterLink = intercepterLink;
}
void setMethod(Method method) {
this.method = method;
}
void setObject(Object object) {
this.object = object;
}
private Object[] getParaValues() {
Object[] paraValues = new Object[] { };
int paraCount = method.getParameterCount();
if (paraCount > 0) {
Class<?>[] methodParaTypes = method.getParameterTypes();
JoinPoint joinPoint = intercepterLink.getJoinPoint();
Object[] paraValue = joinPoint.getParaValues();
if (paraCount == 1 && methodParaTypes[0].equals(JoinPoint.class)) {
return new Object[] { joinPoint };
}
paraValues = new Object[paraCount];
Class<?>[] paraTypes = joinPoint.getParaTypes();
for (int index = 0; index < paraCount; index++) {
if (!methodParaTypes[index].equals(paraTypes[index])) {
continue;
}
paraValues[index] = paraValue[index];
}
}
return paraValues;
}
@Override
public boolean before() {
Object[] paraValues = getParaValues();
Object result = null;
try {
result = method.invoke(object, paraValues);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
if (result != null && method.getReturnType().equals(boolean.class)) {
return (boolean) result;
}
return true;
}
}
前置拦截处理参数的时候,分为三种情况:
1.无参;
2.一个参数,JoinPoint类型;
3.多参,被拦截方法相应的参数;
处理后置拦截也是类似的:
public class AfterIntercepter implements IAfter {
private IntercepterLink intercepterLink;
private Method method;
private Object object;
public AfterIntercepter() {
}
void setIntercepterLink(IntercepterLink intercepterLink) {
this.intercepterLink = intercepterLink;
}
void setMethod(Method method) {
this.method = method;
}
void setObject(Object object) {
this.object = object;
}
private Object[] getParaValues() {
Object[] paraValues = new Object[] { };
int paraCount = method.getParameterCount();
if (paraCount <= 0) {
return paraValues;
}
if (paraCount > 1) {
return paraValues;
}
Class<?>[] methodParaTypes = method.getParameterTypes();
JoinPoint joinPoint = intercepterLink.getJoinPoint();
if (methodParaTypes[0].equals(JoinPoint.class)) {
return new Object[] { joinPoint };
} else if (methodParaTypes[0].equals(ReturnValue.class)) {
return new Object[] { joinPoint.getReturnValue() };
}
return paraValues;
}
@Override
public Object after(Object result) {
Object[] paraValues = getParaValues();
Object res = null;
try {
res = method.invoke(object, paraValues);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
if (res == null) {
return result;
}
ReturnValue returnValue = new ReturnValue();
returnValue.setValue(res);
intercepterLink.getJoinPoint().setReturnValue(returnValue);
return res;
}
}
后置拦截处理参数,也分三种情况:
1.无参;
2.一个参数,JoinPoint类型;
3.一个参数,ReturnValue类型;