前言
这是学习刘老师的《从零开始造Spring》的学习笔记,接上篇笔记从零开始造Spring07
如何实现指定次序的链式调用
SpringAOP定义的拦截器
从类图中我们可以看出Advice 接口继承了来自AOP Aliance 中的MethodInterceptor 类。该类中的invoke 方法通过传入Methodinvocation 对象,而Methodinvocation的proceed方法则是实现链式调用的关键。
ReflectiveMethodInvocation类实现了Methodinvocation 接口
如图我们可以看到ReflectiveMethodInvocation类的构造器中有3个参数,第一个参数是 待拦截的对象,第二个为 待拦截的方法,第三个为 拦截器列表。
关键代码实现
ReflectiveMethodInvocation 中的proceed方法
@Override public Object proceed() throws Throwable { //所有拦截器调用完成 if (this.currentInterceptorIndex == this.interceptors.size() - 1) { return invokeJoinpoint(); } //currentInterceptorIndex初始值为-1 this.currentInterceptorIndex++; MethodInterceptor interceptor = this.interceptors.get(this.currentInterceptorIndex); return interceptor.invoke(this); }
首先会检查传入的拦截器是否调用完成,如果调用完成则返回,否则,则先调用当前拦截器的invoke 方法。
AspectJBeforeAdvice 类的invoke方法
@Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { // 例如:调用TransactionManager的start方法 this.invokeAdviceMethod(); Object proceed = methodInvocation.proceed(); return proceed; }
AspectJAfterReturningAdvice 类的invoke方法
@Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { Object proceed = methodInvocation.proceed(); // 例如:调用TransactionManager的commit方法 this.invokeAdviceMethod(); return proceed; }
比较AspectJBeforeAdvice 类和AspectJAfterReturningAdvice类的invoke方法,我们发现一个明显的区别是invokeAdviceMethod 方法调用顺序,在AspectJBeforeAdvice中首先会调用自身的拦截方法之后才会调用其他的拦截器。在AspectJAfterReturningAdvice中必须等其他的拦截器调用完毕才会调用自身的拦截方法。这就实现了指定次序的链式调用。
相关测试代码
@Test public void testMethodInvocation1() throws Throwable { Method targetMethod = PetStoreService.class.getMethod("placeOrder"); List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(); interceptors.add(afterAdvice); interceptors.add(beforeAdvice); ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(petStoreService, targetMethod, new Object[0], interceptors); mi.proceed(); List<String> msgs = MessageTracker.getMsgs(); Assert.assertEquals(3, msgs.size()); Assert.assertEquals("start tx", msgs.get(0)); Assert.assertEquals("place order", msgs.get(1)); Assert.assertEquals("commit tx", msgs.get(2)); }
通过Factory 获得代理实例
Cglib 动态代理
Cglib动态代理是通过扩展子类来实现对父类的增强。
@Test public void testCallBack() { // Cglib的增强者 Enhancer enhancer = new Enhancer(); // 设置父类 enhancer.setSuperclass(PetStoreService.class); enhancer.setCallback(new TransactionInterceptor()); // 创建代理 PetStoreService petStoreService = (PetStoreService) enhancer.create(); petStoreService.placeOrder(); } //Cglib定义的拦截器 public static class TransactionInterceptor implements MethodInterceptor { TransactionManager txManager = new TransactionManager(); @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { txManager.start(); Object result = proxy.invokeSuper(obj, args); txManager.commit(); return result; } }
通过Factory 获得代理实例
首先我们看一下类图
如类图所示
关键代码:
public class CglibProxyFactory implements AopProxyFactory { //在某种情况下选择对应的拦截器 private static final int AOP_PROXY = 0; private static final int INVOKE_TARGET = 1; private static final int NO_OVERRIDE = 2; private static final int DISPATCH_TARGET = 3; private static final int DISPATCH_ADVISED = 4; private static final int INVOKE_EQUALS = 5; private static final int INVOKE_HASHCODE = 6; protected static final Log logger = LogFactory.getLog(CglibProxyFactory.class); protected final AopConfig config; private Object[] constructorArgs; private Class<?>[] constructorArgTypes; public CglibProxyFactory(AopConfig config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvices().size() == 0 /*&& config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE*/) { throw new AopConfigException("No advisors and no TargetSource specified"); } this.config = config; } @Override public Object getProxy() { return getProxy(null); } //创建代理的方法 @Override public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + this.config.getTargetClass()); } //拿到class对象 Class<?> rootClass = this.config.getTargetClass(); //实例化增强器 Enhancer enhancer = new Enhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); } enhancer.setSuperclass(rootClass); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);//"BySpringCGLIB" enhancer.setInterceptDuringConstruction(false); Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int i = 0; i < types.length; i++) { types[i] = callbacks[i].getClass(); } enhancer.setCallbackFilter(new ProxyCallbackFilter(this.config)); enhancer.setCallbackTypes(types); enhancer.setCallbacks(callbacks); Object proxy = enhancer.create(); return proxy; } private Callback[] getCallbacks(Class<?> rooClass) { //创建Callback Callback aopInterceptor = new DynamicAdvisedInterceptor(this.config); Callback[] callbacks = new Callback[] { aopInterceptor, // AOP_PROXY for normal advice /*targetInterceptor, // INVOKE_TARGET invoke target without considering advice, if optimized new SerializableNoOp(), // NO_OVERRIDE no override for methods mapped to this targetDispatcher, //DISPATCH_TARGET this.advisedDispatcher, //DISPATCH_ADVISED new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised)*/ }; return callbacks; } private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { private final AopConfig config; public DynamicAdvisedInterceptor(AopConfig advised) { this.config = advised; } // @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //获取targetObject Object target = this.config.getTargetObject(); //获取advices列表 List<Advice> chain = this.config.getAdvices(method); Object retVal; //列表为空,啥都不干 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { retVal = methodProxy.invoke(target, args); } else { //生成拦截器列表 List<org.aopalliance.intercept.MethodInterceptor> interceptors = new ArrayList<org.aopalliance.intercept.MethodInterceptor>(); interceptors.addAll(chain); // We need to create a method invocation... retVal = new ReflectiveMethodInvocation(target, method, args, interceptors).proceed(); } return retVal; } } /** * CallbackFilter to assign Callbacks to methods. */ private static class ProxyCallbackFilter implements CallbackFilter { private final AopConfig config; public ProxyCallbackFilter(AopConfig advised) { this.config = advised; } public int accept(Method method) { // 注意,这里做了简化,永远返回第一个 return AOP_PROXY; } }
代码地址