Spring源码分析之——AOP的原理及初始化细节

废话不多说!!!!!! 

AOP 是 Aspect Oriented Programming 的缩写,译为面向切向编程。

原理:Spring AOP的底层源码是基于动态代理和拦截器模式。

对拦截器有疑问的可以看:设计模式之——拦截器模式

为什么要动态代理?

——答:因为业务类本身是不会主动调用切面逻辑(避免耦合),所以业务类必须被代理,由代理类负责调用业务类,并且调用切面;Spring AOP的JDK动态代理的Invocation类是:JdkDynamicAopProxy,这个类完完整整地实现了动态代理以及后续的拦截器模式的切面调用。

AOP调用切面的原理?

——答:AOP的切面调用本质上是一个拦截器模式,通过解析配置文件把Adivce Bean(切面Bean)封装成一个个拦截器(Interceptor),组成一个调用链(chain),在代理类中调用,调用方式同拦截器模式一模一样。

看上图,切面Bean可以实现MethodBeforeAdvice, AfterReturning, Throwing等接口,实现invoke方法,而Spring通过MethodBeforeAdviceInterceptor,AfterReturningAdviceInterceptor等拦截器类封装业务切面Bean,这样就可以持有业务Advice Bean对象,然后在JdkDynamicAopProxy中组装一个拦截器数组,就是chain,进行拦截器模式调用。

 

OK,进入细节!

首先,一个问题:凭什么AOP的Bean就会被动态代理?

要回答这个问题,首先要了解Spring的套路,即:Spring初始化流程中都用了哪些套路?

那就是:BeanPostProcessor后置处理器,这玩意功能很强大,主要负责干的事情就是在Bean实例化(或者注册完)以后做处理。如果是注册完处理,就是对BeanDefinition做修改,如果是实例化后处理,就是进行依赖注入,或者我们现在讨论的动态代理;

那么,每一种处理器都有特定的职责,像依赖注入的处理器是:AutowiredAnnotationBeanPostProcessor,而动态代理的处理器则是:DefaultAdvisorAutoProxyCreator,当然,不止一个处理器可以做动态代理,这里只是我自己的一个例子;

在这张图里,重点关注三个:BeanPostProcessor ,AbstractAutoProxyCreator,DefaultAdvisorAutoProxyCreator,以及方法:postProcessAfterInitialization。

  • BeanPostProcessor :定义接口方法postProcessAfterInitialization

  • AbstractAutoProxyCreator:实现接口方法postProcessAfterInitialization

  • DefaultAdvisorAutoProxyCreator,开启代理功能

 

动态代理的创建逻辑

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

// 这个方法省略了一些代码,保留关键的就可以了
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 注入
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            // 继续完善Bean,AOP的代理就发生在这里
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    return exposedObject;
}

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;
}

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        // 调用后置处理器方法postProcessAfterInitialization
        result = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

 

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator

@Override
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;
}

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.
    // 怎么判断是否需要代理?这里给出了答案:如果有配置Advisers则需要被代理
    // 这里开始去找Advice,Advisor,如果配置了,同时当前的Bean符合要求,就要动态代理
    // 这里说的符合要求,就是advisor配置的正则表达式是否匹配上
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        // 有顾问的Bean,cacheKey=被代理BeanName
        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;
}

 

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator

@Override
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();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 取顾问,同时把顾问Bean给初始化
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

protected List<Advisor> findCandidateAdvisors() {
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

 

——进入取Advisers逻辑,套路一样,通过bean的类型获取,因为Adviser Bean的class配置类都继承了Advisor接口,由此,插一句基础,面向接口编程的核心高度概括起来就是:接口用来表示一类事物,像Spring框架很多空接口就是启到这个作用,类(抽象类)更多地是表示功能抽象。

<!-- 3. 定义Advisor -->
<bean id="logArgsAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
	<property name="advice" ref="logArgsAdvice"></property>
	<property name="pattern" value="org.xxx.service.*.create.*"></property>
</bean>

org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper

public List<Advisor> findAdvisorBeans() {
    // Determine list of advisor bean names, if not cached already.
    String[] advisorNames = null;
    synchronized (this) {
        advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the auto-proxy creator apply to them!
            // 通过Advisor.class得到顾问名称s
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            // 缓存起来
            this.cachedAdvisorBeanNames = advisorNames;
        }
    }
    if (advisorNames.length == 0) {
        return new LinkedList<Advisor>();
    }

    List<Advisor> advisors = new LinkedList<Advisor>();
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                try {
                    // 递归取顾问Bean ★★★★★★★★★★★★★★★★★★★★★★★
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
                            if (logger.isDebugEnabled()) {
                                logger.debug("Skipping advisor '" + name +
                                        "' with dependency on currently created bean: " + ex.getMessage());
                            }
                            // Ignore: indicates a reference back to the bean we're trying to advise.
                            // We want to find advisors other than the currently created bean itself.
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
    }
    return advisors;
}

OK,到这里就完成了AOP动态代理的创建!

 

动态代理的调用逻辑

其实理解了开头的说明,后面就驾轻就熟了。。。。。。。

核心类之一(如果是继承接口的话):org.springframework.aop.framework.JdkDynamicAopProxy

@Override
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()) {
            // 如果没有切面,直接通过AopUtil调用业务代码
            // 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 {
            // 否则,生成调度器ReflectiveMethodInvocation,进行拦截器模式调用
            // 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);
        }
    }
}

org.springframework.aop.framework.ReflectiveMethodInvocation 封装的Invocation

@Override
public Object proceed() throws Throwable {
    //    We start with an index of -1 and increment early.
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        // 拦截器都走完了
        return invokeJoinpoint();
    }

    // 看这个++this.currentInterceptorIndex,是不是一模一样
    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);
    }
}

protected Object invokeJoinpoint() throws Throwable {
    return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}

org.springframework.aop.support.AopUtils


public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
        throws Throwable {

    // Use reflection to invoke the method.
    try {
        ReflectionUtils.makeAccessible(method);
        // 看到了吧,最最尽头的原始动态代理调用
        return method.invoke(target, args);
    }
    catch (InvocationTargetException ex) {
        // Invoked method threw a checked exception.
        // We must rethrow it. The client won't see the interceptor.
        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);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值