(二)Spring AOP的实现-Spring AOP拦截器调用的实现

1.Spring AOP通过JDK的Proxy方式或CGLIB方式生成代理对象的时候,相关的拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过对这些方法的回调来完成的。如果使用JDK的Proxy来生成代理对象,需要通过哦InvocationHandler来设计拦截器回调,如果用CGLIB生成代理对象,需要通过DynamicAdvisedInterceptor来完成回调。

2.JdkDynamicAopProxy的invoke拦截

JdkDynamicAopProxy中生成Proxy对象时,调用如下:Proxy.newInstance(classLoader,proxiedInterfaces,this);这里的this对应的就是InvocationHandler对象,InvocationHandler对象的invoke方法作为Proxy对象的回调函数被触发,从而通过invoke的具体实现完成对目标对象方法调用的拦截或功能增强。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;

TargetSource targetSource = this.advised.targetSource;
Object target = null;

try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 如果目标对象没有实现Object类的基本方法:equals
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 如果目标对象没有实现Object类的基本方法:hashCode
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 根据代理对象的配置来调用服务
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}

Object retVal;

if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}

// 得到目标对象
target = targetSource.getTarget();
Class targetClass = (target != null ? target.getClass() : null);

// 获得拦截器链
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// 如果没有设置拦截器,那么就直接调用target的对应方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相应方法
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 沿着拦截器链继续前进
retVal = invocation.proceed();
}

Class returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}

}

3.Cglib2AopProxy的intercept拦截

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}

target = targetSource.getTarget();

Class targetClass = (target != null ? target.getClass() : null);

                                // 从advised中取得配置好的AOP通知

List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果没有AOP通知配置,那么直接调用target对象的调用方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 通过CglibMethodInvocation来启动advice通知
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}

}

4.目标对象方法的调用

对于使用Jdk的代理对象,是通过AopUtils的invokeJoinpointUsingReflection方法实现的。

public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)

throws Throwable {

// 使用反射调用target对象方法
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// 抛出AOP异常,对异常进行转换
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}

}

对于CglibAopProxy,它对目标对象的调用是通过MethodProxy对象来直接完成的,即methodProxy.invoke(target, args);

5.AOP拦截器链的调用

public Object proceed() throws Throwable {

// 从索引为-1的拦截器开始调用,并按序递增

                // 如果拦截器链中的拦截器迭代调用完毕,这里开始调用target的函数,这个函数通过

                // 反射机制完成

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}

                // 这里沿着定义好的拦截器链进行处理
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

// 这里对拦截器进行动态匹配的判断,如果和定义的PointCut匹配,那么这个

                        // advice将得到执行

InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 如果不匹配,递归调用,直到所有的拦截器都被运行为止
return proceed();
}
}
else {
// 如果是一个interceptor,直接调用这个interceptor对应的方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}

}

6.配置通知器

Object interceptorOrInterceptionAdvice =

this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

对于JdkDynamicAopProxy,interceptorOrInterceptionAdvice为获得的拦截器。

对于Cglib2AopProxy,获取interceptors的操作是由advised对象完成的,这个advised是一个AdvisedSupport对象。

List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

public List getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;

}

advisedChainFactory被配置为DefaultAdvisedChainFactory对象,在DefaultAdvisedChainFactory中实现了interceptor链的获取过程。DefaultAdvisedChainFactorty会通过一个AdvisorAdapterRegistry来实现拦截器的注册,利用AdvisorAdapterRegistry来对从ProxyFactoryBean配置中得到的通知进行适配,从而获取相应的拦截器,再把它加入到设置好的List中,完成拦截器注册。

@Override
public List getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class targetClass) {

                // advisor链已经在config中持有了,这里直接使用

List interceptorList = new ArrayList<>(config.getAdvisors().length);
Class actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
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(actualClass)) {

                                        // 拦截器是通过AdvisorAdapterRegister来加入的

MethodInterceptor[] interceptors = registry.getInterceptors(advisor);

                                        // 使用MethodMatchers的matches方法进行匹配判断

MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
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(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}


return interceptorList;

}

在ProxyFactroyBean的getObjecct方法对advisor进行初始化时,从XML配置中获取了advisor通知器。初始化advisor时,可以通过IoC容器的getBean回调来得到配置好的advisor通知器。

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}

if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}


// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}


// Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}


if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}


else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}


this.advisorChainInitialized = true;

}

advisor通知器的取得是委托给IoC容器完成的,首先,判断这个Bean的类型是不是实现了BeanFactoryAware接口,如果是它一定实现了

BeanFactoryAware定义的接口方法,通过这个接口方法,可以把IoC容器设置到自身定义的一个属性中去。这样,在这个Bean的自身

实现中,就能够得到它所在的IoC容器,从而调用IoC容器的getBean方法,完成对IoC容器的回调。对于IoC容器的使用,如果需要回调

容器,前提是当前的Bean需要实现BeanFactoryAware接口,这个接口只需要实现一个接口方法setBeanFactory,同时设置一个属性来

持有BeanFactory的IoC容器,就可以在Bean中取得IoC容器进行回调了。

7.Advice通知的实现

在为AopProxy代理对象配置拦截器的实现中,有一个取得拦截器的配置过程,这个过程是由DefaultAdvisorChainFactory实现的,而

这个工厂类负责生成拦截器链。在DefaultAdvisorChainFactory的实现中,首先构造了一个GlobalAdvisorAdapterRegistry单件,然后,

对配置的Advisor通知器进行逐个遍历,这些通知器链都是配置在interceptorNames中的;从getInterceptorsAndDynamicInterception

Advice传递进来的advised参数对象中,可以方便地取得配置的通知器,接着就是一个由GlobalAdvisorAdapterRegister来完成的拦截器

的适配和注册过程。

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(actualClass)) {

                                        // 从GlobalAdvisorAdapterRegistry中取得MethodInterceptor的实现

MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// 在getInterceptors方法中创建新的对象实例
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(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}


return interceptorList;

在DefaultAdvisorAdapterRegistry中,设置了一系列的adapter适配器,正是这些adapter适配器的实现,为spring aop的advisor

提供编织能力。

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

        // 持有一个AdvisorAdapter的List,这个List中的Adapter是与实现spring aop的Advice增强功能相对应的
private final List adapters = new ArrayList(3);

        // 加入已有的advice实现的Adapter
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}


@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}


@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {

List interceptors = new ArrayList(3);

                // 从Advisor通知器配置中取得advice通知

Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);

}

                // 对通知进行适配

for (AdvisorAdapter adapter : this.adapters)

if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}


@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}

}

AdvisorAdapter接口设计中的类的层次结构

(二)Spring AOP的实现-Spring AOP拦截器调用的实现_第1张图片

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}


@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}

}

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

private MethodBeforeAdvice advice;

public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}

}

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

private final AfterReturningAdvice advice;

public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}

}

public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {

private static final String AFTER_THROWING = "afterThrowing";

private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);

private final Object throwsAdvice;

private final Map, Method> exceptionHandlerMap = new HashMap, Method>();

public ThrowsAdviceInterceptor(Object throwsAdvice) {
Assert.notNull(throwsAdvice, "Advice must not be null");
this.throwsAdvice = throwsAdvice;

Method[] methods = throwsAdvice.getClass().getMethods();
for (Method method : methods) {
if (method.getName().equals(AFTER_THROWING) &&
(method.getParameterTypes().length == 1 || method.getParameterTypes().length == 4) &&
Throwable.class.isAssignableFrom(method.getParameterTypes()[method.getParameterTypes().length - 1])
) {
// Have an exception handler
this.exceptionHandlerMap.put(method.getParameterTypes()[method.getParameterTypes().length - 1], method);
if (logger.isDebugEnabled()) {
logger.debug("Found exception handler method: " + method);
}
}
}

if (this.exceptionHandlerMap.isEmpty()) {
throw new IllegalArgumentException(
"At least one handler method must be found in class [" + throwsAdvice.getClass() + "]");
}
}

public int getHandlerMethodCount() {
return this.exceptionHandlerMap.size();
}

private Method getExceptionHandler(Throwable exception) {
Class exceptionClass = exception.getClass();
if (logger.isTraceEnabled()) {
logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]");
}
Method handler = this.exceptionHandlerMap.get(exceptionClass);
while (handler == null && exceptionClass != Throwable.class) {
exceptionClass = exceptionClass.getSuperclass();
handler = this.exceptionHandlerMap.get(exceptionClass);
}
if (handler != null && logger.isDebugEnabled()) {
logger.debug("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
}
return handler;
}

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
Method handlerMethod = getExceptionHandler(ex);
if (handlerMethod != null) {
invokeHandlerMethod(mi, ex, handlerMethod);
}
throw ex;
}
}

private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
Object[] handlerArgs;
if (method.getParameterTypes().length == 1) {
handlerArgs = new Object[] { ex };
}
else {
handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
}
try {
method.invoke(this.throwsAdvice, handlerArgs);
}
catch (InvocationTargetException targetEx) {
throw targetEx.getTargetException();
}
}
}

你可能感兴趣的:(spring技术内幕读书笔记)