Fork me on GitHub

spring源码之AOP下篇

 

前言

上篇我们分析了初始化时AOP的特殊处理,本篇来分析依赖注入时的特殊处理。在阅读本篇之前,需要对BeanPostProcessor这个接口熟悉。关于BeanPostProcessor,后面会专门写一篇来专业介绍它。

概述

BeanPostProcessor这个接口提供了两个方法postProcessBeforeInitialization和postProcessAfterInitialization两个方法,子类中实现它们。我们知道依赖注入分为创建bean、注入、初始化三个过程,这两个方法就是在初始化时起作用的。在初始化时,我们已经拿到了一个bean,而BeanPostProcessor的两个方法就是在invokeInitMethods前后分别做一些处理。

上文提到的AspectJAwareAdvisorAutoProxyCreator的类图,我们有必要看一下

我们可以看到AspectJAwareAdvisorAutoProxyCreator其实是BeanPostProcessor的一个实现。AOP的整个核心就是这个类(当然也可以自己扩展,而不用它),而它实现的postProcessAfterInitialization方法是我们分析的核心。AspectJAwareAdvisorAutoProxyCreator在spring经历了下面三个过程。

  • 上篇文章中,我们提到在初始化的特殊处理时默认会注册AspectJAwareAdvisorAutoProxyCreator的BeanDefinition,
  • 而在AbstractApplicationContext的refresh方法中会调用registerBeanPostProcessors方法向容器中注入AspectJAwareAdvisorAutoProxyCreator实例。(后面会更新一篇博文,专门分析refresh方法)
  • 初始化时,AspectJAwareAdvisorAutoProxyCreator能bean进行处理,返回一个代理对象给到用户

 

依赖注入时的特殊处理

 

IOC的依赖注入时,可以分为对象创建、注入、初始化三个步骤。AOP就是在初始化时发生作用的,我们从这开始分析

  • 这个方法我们可以大体看下做了下面几件事情
    • invokeAwareMethods,如果bean实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware,分别设置相应的属性值。(Aware接口后面来一篇专门做个介绍)
    • applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName),调用初始化方法前的处理(接下来进行分析)
    • invokeAwareMethods,实现了InitializingBean或用户定义的初始化方法的处理(后面会开一篇来介绍这个)
    • applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName),调用初始化方法的处理(本篇的分析重点)
//AbstractAutowireCapableBeanFactory类的方法
//初始化bean
protected
Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
  •  调用初始化方法前的处理,对于AOP来说,这个方法没有对bean做任何的处理
//AbstractAutowireCapableBeanFactory类的方法
//循环调用所有后置处理器的postProcessBeforeInitialication方法
public
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
//AbstarctAutoProxyCreator类的方法
//这里得到的是AspectJAwareAdvisorAutoProxyCreator类,而这个方法的实现在其父类AbstractAutoProxyCreato中,没有做任何处理,直接返回
public
Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; }
  • 调用初始化方法后的处理,这里是整个AOP分析核心入口
//AbstractAutowireCapableBeanFactory类的方法
//循环调用后置处理器的postProcessAfterInitialication方法
public
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; }
//AbstractAutoProxyCreator类的方法
//这里方法是整个AOP分析的重要入口,会生成代理返回
public
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
  • 这个方法主要做了以下几个事情
    • 对于不需要进行规则配置的bean直接返回,比如基础类、advisor等。
    • 根据规则匹配,判断当前bean是否需要被拦截,如果不需要,则设置当前bean不需要被代理并缓存,后面再进来就直接返回不需要再判断是否需要被拦截了
    • 需要被拦截的bean就会初代理,并缓存代理Class信息
//AbstractAutoProxyCreator类的方法
//这里会进行判断是否需要代理,需要代理的会进行代理,不需要的就会直接返回
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { 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; }
  • 哪些bean不需要进行规则匹配,就不作介绍了。我们看下如何拿到通过规则匹配,拿到当前bean匹配到的,分为以下几步
    • 前面我们提到对advisor的BeanDefinition信息都注册到容器了,这里第一步就是先拿到所有的advisor name去容器中获取到相应List<advisor>
    • 根据规则匹配到合适的advisor
    • 扩展advisor链表
    • 给advisor排序
//AbstractAdvisorAutoProxyCreator类的方法
//这里就是匹配合适的advisor
protected
Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
//AbstractAdvisorAutoProxyCreator类的方法
//这里就是匹配合适的advisor
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}
  • 寻找所有的advisor,这里比较简单的,就是根据beanName去拿到bean,这里就不贴代码了
  • 寻找匹配的advisor,就是循环每一个advisor的expression表达式进行匹配,合适的话就添加到链表

protected
List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
//AopUtils类的方法
//循环advisor去匹配
public
static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); 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; }
//AopUtils类的方法
//这里我们可以注意到的是第一个判断是基于<aop:decalre-parents>这个标签的,是基于类的过滤。下面的判断是基于<advice:before>等的
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;
    }
}
//AopUtils类的方法
//目标类满足匹配规则并且目前类的方法至少有一个满足匹配规则,这样的类就会被代理
public
static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); 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<Class<?>> classes = new LinkedHashSet<Class<?>>(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; }
  • 合适advisor链表的扩展,如果定义的拦截器链表中包含AspectJ pointcut,那么在链表最前面添加一个ExposeInvocationInterceptor,用于暴露AOP调用。(这个在后面分析拦截链中会用到)

  

//AspectJProxyUtils类的方法
//判断是否需要在拦截器链头加上一个暴露拦截器
public
static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) { // Don't add advisors to an empty list; may indicate that proxying is just not required if (!advisors.isEmpty()) { boolean foundAspectJAdvice = false; for (Advisor advisor : advisors) { // Be careful not to get the Advice without a guard, as // this might eagerly instantiate a non-singleton AspectJ aspect if (isAspectJAdvice(advisor)) { foundAspectJAdvice = true; } } if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) { advisors.add(0, ExposeInvocationInterceptor.ADVISOR); return true; } } return false; } /** * Determine whether the given Advisor contains an AspectJ advice. * @param advisor the Advisor to check */ private static boolean isAspectJAdvice(Advisor advisor) { return (advisor instanceof InstantiationModelAwarePointcutAdvisor || advisor.getAdvice() instanceof AbstractAspectJAdvice || (advisor instanceof PointcutAdvisor && ((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut)); }
  • 根据我们定义的order进行排序,这个比较简单,不再贴代码。到这里我们的advisor有了,后面就可以去生成代理对象了
  • 回到AbstractAutoProxyCreator的方法中,调用了createProxy方法。从createProxy方法向下分析,
    • 直接new一个ProxyFactory
    • 设置属性,这里我们可以关注下面if里面的判断,对应<aop:config>标签proxy-target-class的属性值
    • 创建代理对象 
protected Object createProxy(
        Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    for (Advisor advisor : advisors) {
        proxyFactory.addAdvisor(advisor);
    }

    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    return proxyFactory.getProxy(getProxyClassLoader());
}
  • ProxyFactory创建代理对象,分为两步,创建AopProxy和获取代理对象
//ProxyFactory类的方法
//分为两步,创建AopProxy和获取代理对象
public
Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
  • 创建AopProxy,总结为
    • 如果optimize为true(交给spring去优化)、proxy-target-class设置为true,只实现吧SpringProxy接口,并且target对象本身不是接口并且不是Proxy类的对象,则用cglib代理
    • 否则使用jdk动态代理
//DefualtAopProxyFactory类的方法
//判断使用jdk或cglib动态代理
public
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { 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."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
  • 生成代理,这里只分析jdk,就是简单地获取接口,然后生成实现类。里面有一些细节不再分析
//JdkDynamicAopProxy的方法
//生成jdk代理对象
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, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
  • 到上面代理对象就已经生成了,现在看下调用过程,分为几种处理
    • equals、hashcode不作处理,使用jdkDynamicAopProxy的方法
    • 一些方法的特殊处理(没有做细的分析)
    • <aop:config>标签中的expose-proxy属性在这里进行了设置
    • 拦截器为空,则反射调用
    • 拦截器不为空,分析的重点
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    MethodInvocation invocation;
    Object oldProxy = null;
    boolean setProxyContext = false;

    TargetSource targetSource = this.advised.targetSource;
    Class<?> targetClass = null;
    Object target = null;

    try {
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // The target does not implement the equals(Object) method itself.
            return equals(args[0]);
        }
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // The target does not implement the hashCode() method itself.
            return hashCode();
        }
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;

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

        // May be null. Get as late as possible to minimize the time we "own" the target,
        // in case it comes from a pool.
        target = targetSource.getTarget();
        if (target != null) {
            targetClass = target.getClass();
        }

        // Get the interception chain for this method.
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        // Check whether we have any advice. If we don't, we can fallback on direct
        // reflective invocation of the target, and avoid creating a MethodInvocation.
        if (chain.isEmpty()) {
            // We can skip creating a MethodInvocation: just invoke the target directly
            // Note that the final invoker must be an InvokerInterceptor so we know it does
            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            // We need to create a method invocation...
            invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // Proceed to the joinpoint through the interceptor chain.
            retVal = invocation.proceed();
        }

        // Massage return value if necessary.
        Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target &&
                returnType != Object.class && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // Special case: it returned "this" and the return type of the method
            // is type-compatible. Note that we can't help if the target sets
            // a reference to itself in another returned object.
            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()) {
            // Must have come from TargetSource.
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
  • 拦截器不为空时的调用
    • 如果不是最后一个拦截器,则调用当前拦截器的invoke方法
    • 拦截器的invoke方法,会做一些处理,比如MethodBeforeAdviceInterceptor则会在之前做一些处理,然后再调回proceed方法
    • 回到proceed方法,计数加1,移到下一个拦截器,这样就形成了一条拦截器链
    • 直到最后一个拦截器,不再进行递归,整个方法返回
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);
    }
public Object invoke(MethodInvocation mi) throws Throwable {
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
    return mi.proceed();
}

总结

整个AOP的分析就到此结束,接下来对事务这块的源码做一些分析

参考链接

  • https://wenku.baidu.com/view/6ce3121da300a6c30c229f89.html(核心关注点与横切关注点)
  • https://www.cnblogs.com/syf/archive/2012/05/09/2491780.html(OOP与AOP)
  • https://blog.csdn.net/garfielder007/article/details/78057107(连接点用地概念)
  • https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference(spring官方文档)
  • http://www.cnblogs.com/xrq730/p/6753160.html((源码分析的参考文章)
  • https://blog.csdn.net/elim168/article/details/78166296(@DeclareParents使用)

 

posted @ 2018-07-16 11:31  Lucas2  阅读(152)  评论(0编辑  收藏  举报