1 何时创建代理

doCreateBean是短路操作
AnnotationAwareAspectJAutoProxyCreator(bean工厂级别postProcessor)在所有bean创建时进行了拦截,执行其中的postProcessBeforeInstantiation方法

1.1 postProcessBeforeInstantiation

调用时机

先来回顾一下此方法在Bean创建的过程中的调用时机。
AbstractAutowireCapableBeanFactory.createBean部分源码:
//// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
可以看出,调用发生在Bean实例的创建之前。

AbstractAutoProxyCreator.postProcessBeforeInstantiation:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//1.cacheKey的格式beanClassName_beanName
Object cacheKey = getCacheKey(beanClass, beanName);

  1. //2 从缓存中拿 或 不需要代理直接返回null<br /> //2.1检查缓存已经生成直接返回<br /> if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {<br /> if (this.advisedBeans.containsKey(cacheKey)) {<br /> return null;<br /> }<br /> //2.2isInfrastructureClass检查基础类 如Advice、Pointcut、Advisor、AopInfrastructureBean<br /> // 2.2 shouldSkip检查 子类 aopAdvice和原始类 object String<br /> if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {<br /> this.advisedBeans.put(cacheKey, Boolean.FALSE);<br /> return null;<br /> }<br /> }
  2. //3 创建代理对象并加入缓存
  3. // Create proxy here if we have a custom TargetSource.<br /> // Suppresses unnecessary default instantiation of the target bean:<br /> // The TargetSource will handle target instances in a custom fashion.<br /> // 3.1 获取封装当前bean的TargetSource对象 SpringAOP代理不直接代理target,而需要通过代理TargetSource<br /> // 如果不存在,则直接退出当前方法,否则从TargetSource中获取当前bean对象,并且判断是否需要将切面逻辑应用在当前bean上<br /> TargetSource targetSource = getCustomTargetSource(beanClass, beanName);<br /> if (targetSource != null) {<br /> if (StringUtils.hasLength(beanName)) {<br /> this.targetSourcedBeans.add(beanName);<br /> }<br /> //3.2 获取能够应用当前bean的切面逻辑<br /> Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);<br /> //3.3 根据切面逻辑为当前bean生成代理对象<br /> Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);<br /> this.proxyTypes.put(cacheKey, proxy.getClass());<br /> return proxy;<br /> }
  4. return null;<br /> }<br />

应该代理 ?

Spring首先会对当前的beanClass进行检查(是否应该/可以对其进行代理)。
不应该代理的类分为两种情况:

  • 用于实现AOP的Spring基础类,此种情况在isInfrastructureClass方法中完成检测(单词Infrastructure正是基础设施的意思)。
  • 子类定义的应该跳过的类,默认AbstractAutoProxyCreator的实现直接返回false,即都不应该跳过。
    基础类检测
    AbstractAutoProxyCreator.isInfrastructureClass:
    protected boolean isInfrastructureClass(Class<?> beanClass) {
    boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
    Pointcut.class.isAssignableFrom(beanClass) ||
    Advisor.class.isAssignableFrom(beanClass) ||
    AopInfrastructureBean.class.isAssignableFrom(beanClass);
    return retVal;
    }
    可以看出,任何Advice、Pointcut、Advisor、AopInfrastructureBean的子类都被当做Spring实现AOP的基础设施类。
    跳过类检测
    即shouldSkip方法。前面提到了,AbstractAutoProxyCreator的默认实现直接返回fasle,这一特性被子类AspectJAwareAdvisorAutoProxyCreator重写:
    @Override
    protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    List candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
    if (advisor instanceof AspectJPointcutAdvisor) {
    if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
    return true;
    }
    }
    }
    return super.shouldSkip(beanClass, beanName);
    }
    那么此方法跳过的是谁呢?
    其实就是我们通过aop:aspect标签配置的切面,即:





    里的aopAdvice。
    从前面的aop:aspect一节中可以知道,Spring对于aop:config的解析其实是把aop:before/after等标签解析成为了AspectJPointcutAdvisor类型的BeanDefinition,而aopAdvice以AbstractAspectJAdvice的类型保存在其中。
    所以可以得出结论: Spring跳过的是适用于当前bean的Advisor的Advice/Aspect对象
    AOP逻辑
    那么Spring又是如何找到适用于当前bean的Advisor的呢?
    1:对于XML版本 AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
    protected List findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //1.寻找所有候选的Advisors
    List candidateAdvisors = findCandidateAdvisors();
    //2.判断可以应用的Advisors、 引入introduction处理
    List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    //3扩展Advisor 子类向Advisor链表中添加自己的Advisor
    extendAdvisors(eligibleAdvisors);
    //4 Advisors排序
    if (!eligibleAdvisors.isEmpty()) {
    eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
    }
    2.对于注解版本
    AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors
    protected List findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    List advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    if (this.aspectJAdvisorsBuilder != null) {
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
    }
    Advisor寻找
    AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
    关键便是findCandidateAdvisors方法,此方法将逻辑委托给BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans:
    public List findAdvisorBeans() {
    String[] advisorNames = null;
    synchronized (this) {
    // 结果缓存
    advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
    // 去容器中寻找
    advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    this.beanFactory, Advisor.class, true, false);
    this.cachedAdvisorBeanNames = advisorNames;
    }
    }
    if (advisorNames.length == 0) {
    return new LinkedList();
    }
    List advisors = new LinkedList();
    for (String name : advisorNames) {
    if (isEligibleBean(name)) {
    if (!this.beanFactory.isCurrentlyInCreation(name)) {
    advisors.add(this.beanFactory.getBean(name, Advisor.class));
    }
    }
    }
    return advisors;
    }
    可以看出,首先是从容器中获取到所有的Advisor示例,然后调用isEligibleBean方法逐一判断Advisor是否适用于当前bean。
    适用性检测
    指的便是isEligibleBean方法。最终调用的是AbstractAdvisorAutoProxyCreator的同名方法:
    protected boolean isEligibleAdvisorBean(String beanName) {
    return true;
    }
    而AbstractAdvisorAutoProxyCreator的子类AspectJAwareAdvisorAutoProxyCreator并没有覆盖此方法,所以此处会对容器中所有的Advisor的Advice进行跳过
    检测结果缓存
    因为postProcessBeforeInstantiation方法会在每个bean初始化之前被调用,所以没有必要每次都真的进行基础类检测和跳过类检测,Spring使用了advisedBeans作为缓存用以提高性能。

    TargetSource

    从源码中可以看出,对于自定义的TargetSource,Spring会立即执行代理子类的创建。Spring的代理其实是针对TargetSource的,其类图:
    关于此接口在此不展开叙述。

    1.2 postProcessAfterInitialization(解决早期对象的动态代理)

    AbstractAutoProxyCreator.postProcessAfterInitialization:
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean != null) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    if (!this.earlyProxyReferences.contains(cacheKey)) {
    return wrapIfNecessary(bean, beanName, cacheKey);
    }
    }
    return bean;
    }
    关键便在于wrapIfNecessary方法:
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //自定义TargetSource,已经进行过代理子类生成
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
    return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
    }
    // Create proxy if we have advice.
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    // 创建
    Object proxy = createProxy(
    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    this.proxyTypes.put(cacheKey, proxy.getClass());
    return proxy;
    }
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
    }
    可以看出,在此方法的开头又进行了基础类以及跳过类的检测,再次不再赘述。

    2 Advisor

    2.1 Advisor

    即getAdvicesAndAdvisorsForBean方法,这里进行的便是去容器中寻找适用于当前bean的Advisor,最终调用的是
    AbstractAdvisorAutoProxyCreator.findEligibleAdvisors:
    protected List findEligibleAdvisors(Class<?> beanClass, String beanName) {
    List candidateAdvisors = findCandidateAdvisors();
    List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
    eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
    }
    findCandidateAdvisors前面已经说过了。
    2.2 适用性判断
    findAdvisorsThatCanApply最终调用AopUtils.findAdvisorsThatCanApply:
    public static List findAdvisorsThatCanApply(List candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
    return candidateAdvisors;
    }
    List eligibleAdvisors = new LinkedList();
    for (Advisor candidate : candidateAdvisors) {
    if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
    eligibleAdvisors.add(candidate);
    }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
    if (candidate instanceof IntroductionAdvisor) {
    // already processed
    continue;
    }
    if (canApply(candidate, clazz, hasIntroductions)) {
    eligibleAdvisors.add(candidate);
    }
    }
    return eligibleAdvisors;
    }
    关键在于canApply方法,从源码中可以看出,对于Advisor的判断分为了IntroductionAdvisor以及非IntroductionAdvisor两种情况。
    这种分开处理导致了IntroductionAdvisor在Advisor链中总是位于非IntroductionAdvisor前面
    canApply(candidate, clazz)其实等价于canApply(candidate, clazz, false):
    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    if (advisor instanceof IntroductionAdvisor) {
    return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    else if (advisor instanceof PointcutAdvisor) {
    PointcutAdvisor pca = (PointcutAdvisor) advisor;
    return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
    // It doesn’t have a pointcut so we assume it applies.
    return true;
    }
    }
    很明显,对于引入Advisor与其它Advisor是两种不同的判断方式。
    引入
    引入的概念在下面aop:scoped-proxy中有提到。因为引入的目的在于动态地向一个类添加另一种功能(接口),所以只要判断给定的类是否是要引入到的类即可。
    其它
    AopUtils.canApply:
    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    //是否Pointcut可以匹配当前类
    if (!pc.getClassFilter().matches(targetClass)) {
    return false;
    }
    MethodMatcher methodMatcher = pc.getMethodMatcher();
    //是否Pointcut可以匹配所有方法
    if (methodMatcher == MethodMatcher.TRUE) {
    // No need to iterate the methods if we’re matching any method anyway…
    return true;
    }
    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
    introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }
    Set> classes = new LinkedHashSet>
    (ClassUtils.getAllInterfacesForClassAsSet(targetClass));
    classes.add(targetClass);
    for (Class<?> clazz : classes) {
    Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
    for (Method method : methods) {
    if ((introductionAwareMethodMatcher != null &&
    introductionAwareMethodMatcher
    .matches(method, targetClass, hasIntroductions)) ||
    methodMatcher.matches(method, targetClass)) {
    return true;
    }
    }
    }
    return false;
    }
    Spring的Pointcut由ClassFilter和MethodMatcher两部分组成,其中前者用以判断给定的类是否在Pointcut的匹配范围内,后者用以在ClassFilter匹配满足的情况下判断给定的方法是否在Pointcut匹配的范围内。
    从源码中可以看出,如果ClassFilter匹配得到满足并且Pointcut并不能匹配此类的任意方法,便会用反射的方法获取targetClass(被检测类)的全部方法逐一交由Pointcut的MethodMatcher进行检测
    关于Pointcut表达式是如何解析及存储的在此不再展开。
    Advisor扩展
    AbstractAdvisorAutoProxyCreator.extendAdvisors允许子类向Advisor链表中添加自己的Advisor。子类AspectJAwareAdvisorAutoProxyCreator重写了此方法,其逻辑是:
    如果Advisor链表中的Advisor含有AspectJ Advice,那么将会把一个ExposeInvocationInterceptor添加到链表的表头,目的在于将MethodInvocation以ThreadLocal的方式暴露给后面所有的Advisor,暂不知道具体的用途。

    2.4 排序

    即sortAdvisors方法,用于对实现了Ordered接口的Advisor进行排序。

3 getAdvicesAndAdvisors 转换 Interceptor

4 创建代理

AbstractAutoProxyCreator.createProxy(略去非关键代码):
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {

  1. if (this.beanFactory instanceof ConfigurableListableBeanFactory) {<br /> AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);<br /> }
  2. ProxyFactory proxyFactory = new ProxyFactory();<br /> //1.拷贝当前类的属性<br /> proxyFactory.copyFrom(this);
  3. // 2.判断不是TargetClass<br /> if (!proxyFactory.isProxyTargetClass()) {<br /> if (shouldProxyTargetClass(beanClass, beanName)) {<br /> proxyFactory.setProxyTargetClass(true);<br /> }<br /> else {<br /> evaluateProxyInterfaces(beanClass, proxyFactory);<br /> }<br /> }
  4. // 3 可能是 advise advise需要warp成DefaultPointcutAdvisor 或Advisor<br /> Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);<br /> //4 设置要Advisor封装到proxyFactory 将interceptor适配为Advisor<br /> proxyFactory.addAdvisors(advisors);<br /> //5.<br /> proxyFactory.setTargetSource(targetSource);<br /> //6 定制代理工作<br /> customizeProxyFactory(proxyFactory);<br /> //7 缺省为false 即创建后不允许修改<br /> proxyFactory.setFrozen(this.freezeProxy);<br /> if (advisorsPreFiltered()) {<br /> proxyFactory.setPreFiltered(true);<br /> }<br /> // 8获得代理 cglib或jdk 动态代理<br /> return proxyFactory.getProxy(getProxyClassLoader());<br /> }

4.1 JDK动态代理 or Cglib

由DefaultAopProxyFactory.createAopProxy方法决定使用何种方式创建代理子类。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() ||
hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
Optimize 且没有实现接口 使用JdkDynamicAopProxy
代理类本身是接口或isProxyClass 使用jdk
逻辑很明显,如果指定了(proxy-target-classs设为true)使用Cglib,那么就会使用Cglib的方式,如果没有指定(或为false),那么先回检测被代理类是否实现了自己的接口,如果实现了,那么就采用JDK动态代理的方式。

4.2 使用JDK动态代理

JdkDynamicAopProxy.getProxy:
@Override
public Object getProxy(ClassLoader classLoader) {
//找到可以用来进行代理的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
//用来代理的接口中是否定义了equals或者是hashCode方法?
//结果保存在内部equalsDefined和hashCodeDefined两个成员变量中
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
可以看出,关键的InvocationHandler参数其实就是JdkDynamicAopProxy自身。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;

  1. TargetSource targetSource = this.advised.targetSource;<br /> Object target = null;
  2. try {<br /> //1.Equals方法<br /> if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {<br /> // The target does not implement the equals(Object) method itself.<br /> return equals(args[0]);<br /> }<br /> //2.hashCode方法<br /> else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {<br /> // The target does not implement the hashCode() method itself.<br /> return hashCode();<br /> }<br /> else if (method.getDeclaringClass() == DecoratingProxy.class) {<br /> // There is only getDecoratedClass() declared -> dispatch to proxy config.<br /> return AopProxyUtils.ultimateTargetClass(this.advised);<br /> }<br /> //3<br /> else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&<br /> method.getDeclaringClass().isAssignableFrom(Advised.class)) {<br /> // Service invocations on ProxyConfig with the proxy config...<br /> return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);<br /> }
  3. Object retVal;
  4. //4 处理expose属性,将本代理加入缓存中<br /> if (this.advised.exposeProxy) {<br /> // Make invocation available if necessary.<br /> oldProxy = AopContext.setCurrentProxy(proxy);<br /> setProxyContext = true;<br /> }
  5. // Get as late as possible to minimize the time we "own" the target,<br /> // in case it comes from a pool.<br /> target = targetSource.getTarget();<br /> Class<?> targetClass = (target != null ? target.getClass() : null);
  6. // Get the interception chain for this method.<br /> //5 获得当前方法的调用链<br /> List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  7. // Check whether we have any advice. If we don't, we can fallback on direct<br /> // reflective invocation of the target, and avoid creating a MethodInvocation.<br /> //6.判断调用链是否为空<br /> if (chain.isEmpty()) {<br /> // We can skip creating a MethodInvocation: just invoke the target directly<br /> // Note that the final invoker must be an InvokerInterceptor so we know it does<br /> // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.<br /> //6.1调用链是为空,直接调用invokeJoinpointUsingReflection<br /> Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);<br /> retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);<br /> }<br /> else {<br /> // We need to create a method invocation...<br /> //6.2调用链不为空,封装调用ReflectiveMethodInvocation<br /> MethodInvocation invocation =<br /> new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);<br /> // Proceed to the joinpoint through the interceptor chain.<br /> //6.3 执行拦截器<br /> retVal = invocation.proceed();<br /> }
  8. // Massage return value if necessary.<br /> Class<?> returnType = method.getReturnType();<br /> if (retVal != null && retVal == target &&<br /> returnType != Object.class && returnType.isInstance(proxy) &&<br /> !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {<br /> // Special case: it returned "this" and the return type of the method<br /> // is type-compatible. Note that we can't help if the target sets<br /> // a reference to itself in another returned object.<br /> retVal = proxy;<br /> }<br /> else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {<br /> throw new AopInvocationException(<br /> "Null return value from advice does not match primitive return type for: " + method);<br /> }<br /> return retVal;<br /> }<br /> finally {<br /> if (target != null && !targetSource.isStatic()) {<br /> // Must have come from TargetSource.<br /> targetSource.releaseTarget(target);<br /> }<br /> if (setProxyContext) {<br /> // Restore old proxy.<br /> AopContext.setCurrentProxy(oldProxy);<br /> }<br /> }<br /> }

equals & hashCode

如果被代理类实现了equals或者是hashCode方法,那么生成的代理子类的equals、hashCode方法实际上执行的是JdkDynamicAopProxy相应方法的逻辑。
invoke方法部分源码:
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}

链式调用

对于切点方法,比如前面aop:aspect示例配置中的beforeSend

Spring会创建一个MethodInvocation对象对所有相关的Advisor进行链式调用。invoke相关源码:
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
Object retVal = invocation.proceed();
ReflectiveMethodInvocation.proceed
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 1 procee方法递归出口
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}

  1. // 2获得下一个拦截器<br /> Object interceptorOrInterceptionAdvice =<br /> this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);<br /> // 3区分拦截器类型<br /> // 3,1<br /> if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {<br /> // Evaluate dynamic method matcher here: static part will already have<br /> // been evaluated and found to match.<br /> InterceptorAndDynamicMethodMatcher dm =<br /> (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;<br /> Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());<br /> if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {<br /> return dm.interceptor.invoke(this);<br /> }<br /> else {<br /> // Dynamic matching failed.<br /> // Skip this interceptor and invoke the next in the chain.<br /> return proceed();<br /> }<br /> }<br /> //3。2普通拦截器<br /> //ExploseInvocation delegaratePerTargeObjectInroductionInterceptor<br /> //MethodBeforeAdivceInvocation AspectAfterAdvice AspectAroundAdvice<br /> else {<br /> // It's an interceptor, so we just invoke it: The pointcut will have<br /> // been evaluated statically before this object was constructed.<br /> return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);<br /> }<br /> }

4.3 使用Cglib动态代理


CglibAopProxy.getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace(“Creating CGLIB proxy: “ + this.advised.getTargetSource());
}

  1. try {<br /> Class<?> rootClass = this.advised.getTargetClass();<br /> Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
  2. Class<?> proxySuperClass = rootClass;<br /> if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {<br /> proxySuperClass = rootClass.getSuperclass();<br /> Class<?>[] additionalInterfaces = rootClass.getInterfaces();<br /> for (Class<?> additionalInterface : additionalInterfaces) {<br /> this.advised.addInterface(additionalInterface);<br /> }<br /> }
  3. // Validate the class, writing log messages as necessary.<br /> // 1,校验类<br /> validateClassIfNecessary(proxySuperClass, classLoader);
  4. // Configure CGLIB Enhancer...<br /> //2.配置CGLIB Enhancer<br /> Enhancer enhancer = createEnhancer();<br /> if (classLoader != null) {<br /> enhancer.setClassLoader(classLoader);<br /> if (classLoader instanceof SmartClassLoader &&<br /> ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {<br /> enhancer.setUseCache(false);<br /> }<br /> }<br /> enhancer.setSuperclass(proxySuperClass);<br /> enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));<br /> enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);<br /> enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
  5. //3设置拦截器<br /> Callback[] callbacks = getCallbacks(rootClass);<br /> Class<?>[] types = new Class<?>[callbacks.length];<br /> for (int x = 0; x < types.length; x++) {<br /> types[x] = callbacks[x].getClass();<br /> }<br /> // fixedInterceptorMap only populated at this point, after getCallbacks call above<br /> enhancer.setCallbackFilter(new ProxyCallbackFilter(<br /> this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));<br /> enhancer.setCallbackTypes(types);
  6. // Generate the proxy class and create a proxy instance.<br /> //4创建代理<br /> return createProxyClassAndInstance(enhancer, callbacks);<br /> }<br /> catch (CodeGenerationException | IllegalArgumentException ex) {<br /> throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +<br /> ": Common causes of this problem include using a final class or a non-visible class",<br /> ex);<br /> }<br /> catch (Throwable ex) {<br /> // TargetSource.getTarget() failed<br /> throw new AopConfigException("Unexpected AOP exception", ex);<br /> }<br /> }<br /> private Callback[] getCallbacks(Class<?> rootClass) throws Exception {<br /> // Parameters used for optimization choices...<br /> boolean exposeProxy = this.advised.isExposeProxy();<br /> boolean isFrozen = this.advised.isFrozen();<br /> boolean isStatic = this.advised.getTargetSource().isStatic();
  7. // Choose an "aop" interceptor (used for AOP calls).<br /> //1 將拦截器封装在DynamicAdvisedInterceptor中<br /> Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
  8. // Choose a "straight to target" interceptor. (used for calls that are<br /> // unadvised but can return this). May be required to expose the proxy.<br /> Callback targetInterceptor;<br /> if (exposeProxy) {<br /> targetInterceptor = (isStatic ?<br /> new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :<br /> new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));<br /> }<br /> else {<br /> targetInterceptor = (isStatic ?<br /> new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :<br /> new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));<br /> }
  9. // Choose a "direct to target" dispatcher (used for<br /> // unadvised calls to static targets that cannot return this).<br /> Callback targetDispatcher = (isStatic ?<br /> new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
  10. //2 将拦截器封装Callback<br /> Callback[] mainCallbacks = new Callback[] {<br /> aopInterceptor, // for normal advice<br /> targetInterceptor, // invoke target without considering advice, if optimized<br /> new SerializableNoOp(), // no override for methods mapped to this<br /> targetDispatcher, this.advisedDispatcher,<br /> new EqualsInterceptor(this.advised),<br /> new HashCodeInterceptor(this.advised)<br /> };
  11. Callback[] callbacks;
  12. // If the target is a static one and the advice chain is frozen,<br /> // then we can make some optimizations by sending the AOP calls<br /> // direct to the target using the fixed chain for that method.<br /> if (isStatic && isFrozen) {<br /> Method[] methods = rootClass.getMethods();<br /> Callback[] fixedCallbacks = new Callback[methods.length];<br /> this.fixedInterceptorMap = new HashMap<>(methods.length);
  13. // TODO: small memory optimization here (can skip creation for methods with no advice)<br /> for (int x = 0; x < methods.length; x++) {<br /> Method method = methods[x];<br /> List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);<br /> fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(<br /> chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());<br /> this.fixedInterceptorMap.put(method, x);<br /> }
  14. // Now copy both the callbacks from mainCallbacks<br /> // and fixedCallbacks into the callbacks array.<br /> callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];<br /> System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);<br /> System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);<br /> this.fixedInterceptorOffset = mainCallbacks.length;<br /> }<br /> else {<br /> callbacks = mainCallbacks;<br /> }<br /> return callbacks;<br /> }<br />DynamicAdvisedInterceptor.intercept<br /> public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {<br /> Object oldProxy = null;<br /> boolean setProxyContext = false;<br /> Object target = null;<br /> TargetSource targetSource = this.advised.getTargetSource();<br /> try {<br /> if (this.advised.exposeProxy) {<br /> // Make invocation available if necessary.<br /> oldProxy = AopContext.setCurrentProxy(proxy);<br /> setProxyContext = true;<br /> }<br /> // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...<br /> target = targetSource.getTarget();<br /> Class<?> targetClass = (target != null ? target.getClass() : null);<br /> // 1.获得拦截器链<br /> List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);<br /> Object retVal;<br /> // Check whether we only have one InvokerInterceptor: that is,<br /> // no real advice, but just reflective invocation of the target.
  15. if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {<br /> // We can skip creating a MethodInvocation: just invoke the target directly.<br /> // Note that the final invoker must be an InvokerInterceptor, so we know<br /> // it does nothing but a reflective operation on the target, and no hot<br /> // swapping or fancy proxying.<br /> Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);<br /> // 1.1拦截器链为空直接调用<br /> retVal = methodProxy.invoke(target, argsToUse);<br /> }<br /> else {<br /> // We need to create a method invocation...<br /> // 1.2进去拦截器链<br /> retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();<br /> }<br /> retVal = processReturnType(proxy, target, method, retVal);<br /> return retVal;<br /> }<br /> finally {<br /> if (target != null && !targetSource.isStatic()) {<br /> targetSource.releaseTarget(target);<br /> }<br /> if (setProxyContext) {<br /> // Restore old proxy.<br /> AopContext.setCurrentProxy(oldProxy);<br /> }<br /> }<br /> }

4 小结

1、 @EnableAspectJAutoProxy 开启AOP功能
2、 @EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator
3、AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;
4、容器的创建流程:
1)、registerBeanPostProcessors()注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象
2)、finishBeanFactoryInitialization()初始化剩下的单实例bean
1)、创建业务逻辑组件和切面组件
2)、AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程
3)、组件创建完之后,判断组件是否需要增强
是:切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib);
5)、执行目标方法:
1)、代理对象执行目标方法
2)、CglibAopProxy.intercept();
1)、得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor
2)、利用拦截器的链式机制,依次进入每一个拦截器进行执行;
3)、效果:
正常执行:前置通知-》目标方法-》后置通知-》返回通知
出现异常:前置通知-》目标方法-》后置通知-》异常通知

参考

https://www.cnblogs.com/liuyk-code/p/9886033.html