前言
这是学习刘老师的《从零开始造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;
}
}