Spring源码学习(7)——AOP

我们知道,使用面对对象编程的时候有一些弊端,当需要为多个不具有继承关系的对象引入同一个公共行为时,例如日志、安全检测等,所以就有了一个对面对对象编程的补充,即面对切面编程(AOP),AOP所关注的方向是横向的,不同于OOP的纵向。

Spring2.0采用@AspectJ注解来定义一个包含切点信息和增强横切逻辑的切面,这样的方案比采用配置的方案要来得更方便。

那要支持注解方式的AOP,首先需要在配置文件中添加一行配置

<aop:aspectj-autoproxy/>

我们的分析首先就从这里开始。之前自定义标签的随笔中提到了如何自定义标签的方法,这里的aop也是一个自定义配置,我们可以根据scheme文件定位到这个注解的具体解析器。

public class AopNamespaceHandler extends NamespaceHandlerSupport {
public AopNamespaceHandler() {
} public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}

可以看出,对于aspect-aotoproxy的解析工作在AspectJAutoProxyBeanDefinitionParser中

解析方法是这个类的parse方法

public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
this.extendBeanDefinition(element, parserContext);
return null;
}

继续进入到registerAspectJAnnotationAutoProxyCreatorIfNecessary 方法中

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}

实际上这个方法主要做了三件事情:

1、注册或者升级AnnotationAwareAspectJAutoProxyCreator

2、处理proxy-target-class以及expose-proxy属性

3、最后注册组件并通知,便于监听器做进一步处理

先来看第一条,对于AOP的实现基本都是靠AnnotationAwareAspectJAutoProxyCreator去完成的

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if(registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition beanDefinition1 = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if(!cls.getName().equals(beanDefinition1.getBeanClassName())) {
int currentPriority = findPriorityForClass(beanDefinition1.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if(currentPriority < requiredPriority) {
beanDefinition1.setBeanClassName(cls.getName());
}
} return null;
} else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Integer.valueOf(-2147483648));
beanDefinition.setRole(2);
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}

这段代码里首先先判断容器中是否已经存在了代理创建器,且与当前的不一致,如果存在,那么spring会根据代理创建器的优先级,确定使用哪一个代理创建器。

如果容器中不存在已有的代理创建器,那么spring就会生成一个默认的,且优先级最低的代理创建器。

接下来到了第二步

    private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if(sourceElement != null) {
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute("proxy-target-class")).booleanValue();
if(proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
} boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute("expose-proxy")).booleanValue();
if(exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
} }

这里对proxy-target-class属性和expose-proxy属性进行了设置。

proxy-target-class:AOP生成代理的默认策略是:如果被代理的目标对象实现了至少一个接口,那么就会使用JDK动态代理,所有该目标类型实现的接口都会被代理,如果该目标类型没有实现任何接口,那么spring就会生成一个CGLIB代理

proxy-target-class属性可以强制spring对目标类生成CGLIB代理。

expose-proxy:有时候目标对象内部的自我调用将无法实施切面中的增强,这时候就可以设置expose-proxy为true暴露代理,然后在自我调用的时候使用AopContext.currentProxy()获取当前的代理。

之前的内容讲解了通过自定义配置完成了对AnnotationAwareAspectJAutoProxyCreator的自动注册,那么这个类到底做了什么工作来完成AOP的工作呢?

我们看一下这个类的UML图

aaarticlea/png;base64,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" alt="" />

我们可以看到这个类实现了BeanPostProcessor这个接口,每当Spring加载这个Bean时会在实例化前调用其方法,说明对于aop的实现就在这里。

我们走进它实现的postprocessAfterInitialization这个方法。

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
} return bean;
}

这里的wrapIfNecessary方法根据字面意思可以看出就是对当前bean做了包装,我们进入到这个方法中

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}

首先在第一段if逻辑中,Spring检查了当前bean是否已经被代理过,在targetSourcedBeans中维护了所有已经被代理过的beanName,如果已经代理过,那么就只需直接返回即可。

第二段if逻辑中,Spring会判断当前bean是否在不需要代理的bean列表中,如果在话,那么就直接返回当前bean即可。

第三段if逻辑中,Spring判断了当前这个bean是否是基础设施类,如果是的话就无需对其做代理了。所谓的基础设施类根据源码来看就是一下几类

Advice、Pointcut、Advisor和AopInfrastructureBean

第四段那就说明当前bean无需做代理,那么在advisedBeans中当前的bean就被设置为无需代理的类

重要的逻辑显然在第三段if逻辑中,看一下这段

首先getAdvicesAndAdvisorsForBean这个方法是对增强方法生成代理,具体逻辑在findEligibleAdvisors中

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
} return eligibleAdvisors;
}

首先是找到候选的增强器

protected List<Advisor> findCandidateAdvisors() {
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
} return advisors;
}

这个方法中可以看到首先会调用父类的findCandidateAdvisors方法获取配置中的增强。

获取注解中的增强就是在buildAspectJAdvisors方法中

public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized(this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList();
List<String> aspectNames = new LinkedList();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
String[] var18 = beanNames;
int var19 = beanNames.length; for(int var7 = 0; var7 < var19; ++var7) {
String beanName = var18[var7];
if (this.isEligibleBean(beanName)) {
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType != null && this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
} else {
this.aspectFactoryCache.put(beanName, factory);
} advisors.addAll(classAdvisors);
} else {
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton");
} MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
} this.aspectBeanNames = aspectNames;
return advisors;
}
}
}

这段代码里

1)首先会获取容器中的所有bean,BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false),这个方法就是获取所有Object类的bean,实际上就是所有bean

2)如果当前bean是Aspect类型,那么根据aspect是否是单例,通过this.advisorFactory.getAdvisors(factory)来获取增强

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
this.validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new LinkedList();
Iterator var6 = this.getAdvisorMethods(aspectClass).iterator(); while(var6.hasNext()) {
Method method = (Method)var6.next();
Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
} if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
} Field[] var12 = aspectClass.getDeclaredFields();
int var13 = var12.length; for(int var14 = 0; var14 < var13; ++var14) {
Field field = var12[var14];
Advisor advisor = this.getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
} return advisors;
}

首先在this.getAdvisorMethods方法中,会在当前aspect中找到所有非Pointcut注解的所有方法,并对方法进行排序。

拿到了所有方法后,会遍历所有方法并获取增强

接下来考虑到配置中可能会将增强配置成延迟初始化,那么需要在首位加入同步实例化增强器以保证增强使用之前的实例化

最后是是对DeclareParents注解的获取

我们首先看一下获取增强的方法

1)获取切点信息

@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
} else {
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
} return ajexp;
}
}

这里会拿到所有的Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class注解,接下来会获取注解中的表达式,例如@Pointcut(execution(**.test*(..)))中的execution(**.test*(..))

拿到这些内容后将解析的结果封装到 AspectJExpressionPointcut类中

2)根据切点信息生成增强

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Pointcut preInstantiationPointcut = Pointcuts.union(aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
this.pointcut = new InstantiationModelAwarePointcutAdvisorImpl.PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory, null);
this.lazy = true;
} else {
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = this.instantiateAdvice(this.declaredPointcut);
} }

这里就是讲增强的信息封装成InstantiationModelAwarePointcutAdvisorImpl类,同时针对不同的增强会通过不同的逻辑实现

@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
this.validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
} else if (!this.isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]");
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Found AspectJ method: " + candidateAdviceMethod);
} Object springAdvice;
switch(aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning)aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
((AbstractAspectJAdvice)springAdvice).setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing)aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
((AbstractAspectJAdvice)springAdvice).setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (this.logger.isDebugEnabled()) {
this.logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
} return null;
default:
throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);
} ((AbstractAspectJAdvice)springAdvice).setAspectName(aspectName);
((AbstractAspectJAdvice)springAdvice).setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
((AbstractAspectJAdvice)springAdvice).setArgumentNamesFromStringArray(argNames);
} ((AbstractAspectJAdvice)springAdvice).calculateArgumentBindings();
return (Advice)springAdvice;
}
}

这里针对不同的增强类型生成了不同的增强器。增强器中实现了对于的接口方法,例如AtBefore实现了MethodBeforeAdvice接口,AtAfter则是实现了MethodInterceptor的invoke方法,在方法里使用了finilly代码块保证在所代理的方法执行后调用切面方法。

完成了所有增强器的解析后,接下来就需要从中挑选出使用于当前Bean的增强器, 这段逻辑在this.findAdvisorsThatCanApply方法中

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if(candidateAdvisors.isEmpty()) {
return candidateAdvisors;
} else {
LinkedList eligibleAdvisors = new LinkedList();
Iterator hasIntroductions = candidateAdvisors.iterator(); while(hasIntroductions.hasNext()) {
Advisor candidate = (Advisor)hasIntroductions.next();
if(candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
} boolean hasIntroductions1 = !eligibleAdvisors.isEmpty();
Iterator candidate2 = candidateAdvisors.iterator(); while(candidate2.hasNext()) {
Advisor candidate1 = (Advisor)candidate2.next();
if(!(candidate1 instanceof IntroductionAdvisor) && canApply(candidate1, clazz, hasIntroductions1)) {
eligibleAdvisors.add(candidate1);
}
} return eligibleAdvisors;
}
}

这部分代码并没有理解得特别清楚,待后续补充

在获取了所有对应bean的增强后,便可以进行代理的创建了

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if(!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class targetClass = config.getTargetClass();
if(targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass)?new ObjenesisCglibAopProxy(config):new JdkDynamicAopProxy(config));
}
}
}

首先会根据策略判断是使用JDK代理还是CGLIB代理,判断的依据是:

1、optimize:是否使用激进的优化策略,除非完全了解AOP代理如何处理优化,否则不推荐使用这个配置

2、proxyTargetClass:这个属性为true时,会统一使用CGLIB生产代理

3、根据spring默认的代理策略,如果这个类实现了接口,那么就使用JDK代理,反之,使用CGLIB代理

确定了使用哪种代理方式后,就可以进行代理的创建了

1)JDK代理

JDK代理的核心实际上就是要创建InvocationHandler,Spring用的是继承InvocationHandler的JdkDynamicAopProxy

这里面有两个方法尤为关键

1、getProxy

    public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
} Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

在这段代码中,首先获取了当前bean的所有接口,并通过Proxy.newProxyInstance方法,将所有接口代理成自己(也就是InvocationHandler)

2、invoke

invoke是InvocationHandler接口的一个接口方法,当代理的方法被调用时,实际上调用的就是这个方法

@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null; Object var13;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
Boolean var19 = this.equals(args[0]);
return var19;
} if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
Integer var18 = this.hashCode();
return var18;
} if (method.getDeclaringClass() == DecoratingProxy.class) {
Class var17 = AopProxyUtils.ultimateTargetClass(this.advised);
return var17;
} Object retVal;
if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
return retVal;
} if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
} target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
MethodInvocation 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);
} var13 = retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
} if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
} } return var13;
}

首先,如果调用的是equals方法和hashcode方法,spring会做特殊的处理,经过一系列处理之后,接下来spring会拿到当前方法的拦截器链

如果拦截器链为空,那么就直接调用切点方法

如果有,那么会通过ReflectiveMethodInvocation对拦截器链进行封装

最后调用拦截器链

我们来看具体的调用方法

    public Object proceed() throws Throwable {
if(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)?dm.interceptor.invoke(this):this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}

这里逻辑比较简单,就是遍历每一个拦截器,并按顺序调用拦截器的invoke方法,如果是动态的,就需要匹配一下,如果是普通的拦截器,直接调用即可。

2)CGLIB代理

CGLIB是一个强大的高性能的代码生成包,底层通过使用一个小而快的字节码处理器框架ASM,来转换字节码并生成新的类

public Object getProxy(ClassLoader classLoader) {
if(logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
} try {
Class ex = this.advised.getTargetClass();
Assert.state(ex != null, "Target class must be available for creating a CGLIB proxy");
Class proxySuperClass = ex;
int x;
if(ClassUtils.isCglibProxyClass(ex)) {
proxySuperClass = ex.getSuperclass();
Class[] enhancer = ex.getInterfaces();
Class[] callbacks = enhancer;
int types = enhancer.length; for(x = 0; x < types; ++x) {
Class additionalInterface = callbacks[x];
this.advised.addInterface(additionalInterface);
}
} this.validateClassIfNecessary(proxySuperClass, classLoader);
Enhancer var12 = this.createEnhancer();
if(classLoader != null) {
var12.setClassLoader(classLoader);
if(classLoader instanceof SmartClassLoader && ((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass)) {
var12.setUseCache(false);
}
} var12.setSuperclass(proxySuperClass);
var12.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
var12.setNamingPolicy(SpringNamingPolicy.INSTANCE);
var12.setStrategy(new CglibAopProxy.ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] var13 = this.getCallbacks(ex);
Class[] var14 = new Class[var13.length]; for(x = 0; x < var14.length; ++x) {
var14[x] = var13[x].getClass();
} var12.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
var12.setCallbackTypes(var14);
return this.createProxyClassAndInstance(var12, var13);
} catch (CodeGenerationException var9) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: Common causes of this problem include using a final class or a non-visible class", var9);
} catch (IllegalArgumentException var10) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: Common causes of this problem include using a final class or a non-visible class", var10);
} catch (Exception var11) {
throw new AopConfigException("Unexpected AOP exception", var11);
}
}

CGLIB代理简单来说就是生成一个Enhancer类,然后设置它的代理对象,以及callback方法,

代理的逻辑就做callback里面

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
CglibAopProxy.DynamicAdvisedInterceptor aopInterceptor = new CglibAopProxy.DynamicAdvisedInterceptor(this.advised);
Object targetInterceptor;
if(exposeProxy) {
targetInterceptor = isStatic?new CglibAopProxy.StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()):new CglibAopProxy.DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
} else {
targetInterceptor = isStatic?new CglibAopProxy.StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()):new CglibAopProxy.DynamicUnadvisedInterceptor(this.advised.getTargetSource());
} Callback targetDispatcher = (Callback)(isStatic?new CglibAopProxy.StaticDispatcher(this.advised.getTargetSource().getTarget()):new CglibAopProxy.SerializableNoOp());
Callback[] mainCallbacks = new Callback[]{aopInterceptor, (Callback)targetInterceptor, new CglibAopProxy.SerializableNoOp(), targetDispatcher, this.advisedDispatcher, new CglibAopProxy.EqualsInterceptor(this.advised), new CglibAopProxy.HashCodeInterceptor(this.advised)};
Callback[] callbacks;
if(isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap(methods.length); for(int x = 0; x < methods.length; ++x) {
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = new CglibAopProxy.FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(methods[x].toString(), Integer.valueOf(x));
} callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
} else {
callbacks = mainCallbacks;
} return callbacks;
}

在这里spring会将advised封装至DynamicAdvisedInterceptor中,DynamicAdvisedInterceptor继承了methodInterceptor的接口,在实际调用的时候,会执行这个接口的invoke方法。

实际上JDK代理和CGLIB的实现方式大同小异,首先都是构造链,然后进行链的调用。

上一篇:Android 开发笔记——通过 Intent 传递类对象


下一篇:ASA与PIX的区别