github地址:GitHub - CodePpoi/spring-code
学习了TDD测试驱动,觉得得拿个东西来练手,想起之前写的AOP一直写不出来,就用测试驱动的方法来完成,没想到还真写出来了。
首先记录自己写测试的时候,列出的代办事项,后面的d表示done,完成的意思
//调用时获得的是代理对象 //先执行实际方法d //後执行代理对象的方法 before + 1 d //把代理对象改为JDK代理 d //调用测试通过 d //把before和after移动到beforeAdvice和After d //调用BeforeAdvice和AfterAdvice d //调用BeforeAdvice和AfterAdvice interceptor d //用Chain调用 interceptor d //用JDK代理调用chain d //使用注解的方式添加advisior buildAdvisor //添加Before和After注解 //before advice和 before联系起来 //advisior和before advice联系起来 add //advice和intecep 联系起来 d
测试通过打印输出来完成,代码
public static void main(String[] args) throws Throwable {
AnnotationAOPProxyCreator a = new AnnotationAOPProxyCreator();
final BizAImpl bizAImpl = new BizAImpl();
List<Advisor> advisors = a.buildAdvisors();
//buildAdvisors(BizAImpl.class.getDeclaredMethod("doSomething"));
JdkDynamicProxyImpl jdkDynamicProxy = new JdkDynamicProxyImpl(advisors, bizAImpl);
jdkDynamicProxy.invoke(bizAImpl, BizAImpl.class.getDeclaredMethod("doSomething"), null);
//final IBizA newBizA = (IBizA) createProxy(bizAImpl);
//newBizA.doSomething();
}
对应的输出为:
其实代理,就是给原对象加了一层List<Advisor> advisors,
List<Advisor> advisors = a.buildAdvisors();
//buildAdvisors(BizAImpl.class.getDeclaredMethod("doSomething"));
JdkDynamicProxyImpl jdkDynamicProxy = new JdkDynamicProxyImpl(advisors, bizAImpl);
那么到底是怎么加的呢,
private List<Advisor> getAdvisorsByAspect(Class class1) {
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(class1)) {
Advisor advisor = null;
try {
advisor = getAdvisor(method, class1.getAnnotation(Aspect.class));
} catch (Exception e) {
//e.printStackTrace();
}
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
首先通过getAdvisorMethods获取对应class的所有方法,然后调用getAdivsor
private Advisor getAdvisor(Method method, Object aspect) {
Advisor advisor = null;
Advice advice = getAdvice(method, aspect);
if(advice == null) return advisor;
advisor = new Advisor();
advisor.setAspect((Aspect)aspect);
advisor.setPointcut(getPointcut(method));
advisor.setAdvice(advice);
return advisor;
}
这个方法里有设置advice,advice又是从getAdvice获取的:
private Advice getAdvice(Method method, Object aspect) {
if(isBefore(method)) {
return new BeforeAdvice(method, (Aspect) aspect);
}
if(isAfter(method)) {
return new AfterAdvice(method, (Aspect) aspect);
}
return null;
}
也就顺其自然的引入了BeforeAdvice,上面的代码就是把@MyBefore和Advice关联起来,那么标注了@MyBefore的方法也就会执行,intecept方法
public class BeforeAdvice extends Advice implements MyMethodInterceptor {
public BeforeAdvice(Method adviceMethod, Aspect aspect) {
super(adviceMethod, aspect);
// TODO Auto-generated constructor stub
}
public void before(final Object target, final Method method, final Object[] args) {
this.invokeAspectMethod(target, method, args);
}
@Override
public Object intercept(Method method, Object[] arguments, Object target, MethodInterceptorChain chain) {
//before(target);
//this.before(target, method, arguments);
try {
adviceMethod.invoke(new Logging(), arguments);//第一个参数必为对象实例
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return chain.intercept(method, arguments, target);
}
}
那么intecept在哪执行:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MyMethodInterceptor[] iterceptors =
AdvisorHelper.getMethodInterceptors(this.getAdvisors(), method);
Object obj = new MethodInterceptorChain(iterceptors)
.intercept(method,args,proxy);
return obj;
}
就是在jdk代理执行invoke方法是,会先根据Adivsor获取一个拦截器组,然后顺着这个责任链,一步一步的调用下去,也就会执行到BeforeAdvice里面了。
TDD最常用的就是伪实现,也正是这个技巧让我成功实现了AOP,不然头都是晕的=.=