没搬过来《Spring设计思想》AOP实现原理(基于JDK和基于CGLIB)
1 Spring AOP代理对象的生成(基于JDK代理)
Spring提供了两种方式来生成代理对象: JDKProxy
和Cglib
,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是
如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。下面我们来研究一下Spring如何使用JDK来生成代理对象
,具体的生成代码放在JdkDynamicAopProxy这个类中,直接上相关代码:
/**
* <ol>
* <li>获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false)
* <li>检查上面得到的接口中有没有定义 equals或者hashcode的接口
* <li>调用Proxy.newProxyInstance创建代理对象
* </ol>
*/
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);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
那这个其实很明了,注释上我也已经写清楚了,不再赘述。
下面的问题是,代理对象生成了,那切面是如何织入的?
我们知道InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。而通过JdkDynamicAopProxy的签名我们可以看到这个类其实也实现了InvocationHandler,下面我们就通过分析这个类中实现的invoke()方法来具体看下Spring AOP是如何织入切面的。
publicObject invoke(Object proxy, Method method, Object[] args) throwsThrowable {
MethodInvocation invocation = null;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class targetClass = null;
Object target = null;
try {
//eqauls()方法,具目标对象未实现此方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)){
return (equals(args[0])? Boolean.TRUE : Boolean.FALSE);
}
//hashCode()方法,具目标对象未实现此方法
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)){
return newInteger(hashCode());
}
//Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
if (!this.advised.opaque &&method.getDeclaringClass().isInterface()
&&method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations onProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised,method, args);
}
Object retVal = null;
if (this.advised.exposeProxy) {
// Make invocation available ifnecessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//获得目标对象的类
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
//获取可以应用到此方法上的Interceptor列表
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);
//如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)
if (chain.isEmpty()) {
retVal = AopUtils.invokeJoinpointUsingReflection(target,method, args);
} else {
//创建MethodInvocation
invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
// Massage return value if necessary.
if (retVal != null && retVal == target &&method.getReturnType().isInstance(proxy)
&&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned"this" and the return type of the method
// is type-compatible. Notethat we can't help if the target sets
// a reference to itself inanother returned object.
retVal = proxy;
}
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
// Must have come fromTargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
主流程可以简述为:获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint; 如果没有,则直接反射执行joinpoint。而这里的关键是通知链是如何获取的
以及它又是如何执行的
,下面逐一分析下。
首先,从上面的代码可以看到,通知链是通过Advised.getInterceptorsAndDynamicInterceptionAdvice()这个方法来获取的,我们来看下这个方法的实现:
public List<Object>getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {
MethodCacheKeycacheKey = new MethodCacheKey(method);
List<Object>cached = this.methodCache.get(cacheKey);
if(cached == null) {
cached= this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this,method, targetClass);
this.methodCache.put(cacheKey,cached);
}
returncached;
}
可以看到实际的获取工作其实是由AdvisorChainFactory. getInterceptorsAndDynamicInterceptionAdvice()这个方法来完成的,获取到的结果会被缓存。
下面来分析下这个方法的实现:
/**
* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
*/
publicList getInterceptorsAndDynamicInterceptionAdvice(Advised config, Methodmethod, Class targetClass) {
// This is somewhat tricky... we have to process introductions first,
// but we need to preserve order in the ultimate list.
List interceptorList = new ArrayList(config.getAdvisors().length);
//查看是否包含IntroductionAdvisor
boolean hasIntroductions = hasMatchingIntroductions(config,targetClass);
//这里实际上注册一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptor
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
for (int i = 0; i <advisors.length; i++) {
Advisor advisor = advisors[i];
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor= (PointcutAdvisor) advisor;
if(config.isPreFiltered() ||pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
//TODO: 这个地方这两个方法的位置可以互换下
//将Advisor转化成Interceptor
MethodInterceptor[]interceptors = registry.getInterceptors(advisor);
//检查当前advisor的pointcut是否可以匹配当前方法
MethodMatcher mm =pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm,method, targetClass, hasIntroductions)) {
if(mm.isRuntime()) {
// Creating a newobject instance in the getInterceptors() method
// isn't a problemas we normally cache created chains.
for (intj = 0; j < interceptors.length; j++) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j],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;
}
这个方法执行完成后,Advised中配置能够应用到连接点或者目标类的Advisor全部被转化成了MethodInterceptor。
接下来我们再看下得到的拦截器链是怎么起作用的。
if (chain.isEmpty()) {
retVal = AopUtils.invokeJoinpointUsingReflection(target,method, args);
} else {
//创建MethodInvocation
invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
从这段代码可以看出,如果得到的拦截器链为空,则直接反射调用目标方法,否则创建MethodInvocation,调用其proceed方法,触发拦截器链的执行,来看下具体代码
public Object proceed() throws Throwable {
// We start with an index of -1and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()- 1) {
//如果Interceptor执行完了,则执行joinPoint
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果要动态匹配joinPoint
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)) {
//执行当前Intercetpor
returndm.interceptor.invoke(this);
}
else {
//动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcutwill have
// been evaluated statically before this object was constructed.
//执行当前Intercetpor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}