总所周知,Spring通过动态代理的方式实现AOP处理,那么当我们调用一个被AOP处理的方法,其内部是如何实现的呢?
我们以Jdk动态代理为例,当我们访问代理对象到最后访问目标方法,JdkDynamicAopProxy采用了如下步骤:
- 调用Proxy.newProxyInstance()生成JdkDynamicAopProxy对象
- 调用该对象的invoke()方法;
- 然后匹配通知类型调用通知(通知就是@Before、@After等等);
- 最后调用目标方法。
Jdk动态代理使用getProxy方法获取代理对象,进入getProxy方法:
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
classloader:类加载器,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
proxiedInterfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口
this:表示JdkDynamicAopProxy自身,因为JdkDynamicAopProxy实现了InvocationHandler接口
调用代理对象的invoke方法,进入invoke方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
…………
//获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
//直接调用target的对应方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
} else {
//先调用拦截器,再调用目标方法
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
…………
}
匹配通知类型调用通知
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class targetClass) {
// This is somewhat tricky... we have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
这里先获取拦截器链,跟踪getInterceptorsAndDynamicInterceptionAdvice方法,其实此处使用了适配器的设计模式,将配置的通知Advisor转化成拦截器Interceptor。
调用目标方法
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
可以看到,此处循环调用processd方法,如果currentInterceptorIndex =-1,表示所有的拦截器调用完毕,接下来调用目标方法。
适配器模式
- 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。——Gang of Four