spring mvc拦截器,spring拦截器以及AOP切面的区别和源码

本文详细解析了SpringMVC拦截器的执行流程,从HandlerInterceptor的preHandle到postHandle再到afterCompletion。同时,对比了Spring AOP的MethodInterceptor,探讨了AOP的切面、连接点、通知等概念,以及Spring如何判断bean是否需要被代理的源码分析。文章还介绍了Advisor类架构及其在Spring AOP中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringMVC 拦截器执行时机

对于springmvc,有两种方式配置拦截器。

一是实现HandlerInterceptor接口,如

public class MyInterceptor1 implements HandlerInterceptor {
    //该方法在action执行前执行,可以实现对数据的预处理,
    // 比如:编码、安全控制等。如果方法返回true,则继续执行action。
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
            Exception {
        System.out.println("MyInterceptor1 action之前执行!!!");
        return true;  //继续执行action
    }
 
    该方法在action执行后,生成视图前执行。在这里,我们有机会修改视图层数据。
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
            modelAndView) throws Exception {
        System.out.println("MyInterceptor1 action执行之后,生成视图之前执行!!");
    }
 
    //最后执行,通常用于释放资源,处理异常。我们可以根据ex是否为空,来进行相关的异常处理。
    //因为我们在平时处理异常时,都是从底层向上抛出异常,最后到了spring框架从而到了这个方法中。
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1 最后执行!!!一般用于释放资源!!");
    }
}

二是extends HandlerInterceptorAdapter类(是HandlerInterceptor的子类),如

public class MyInterceptor2  extends HandlerInterceptorAdapter{
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
            Exception {
        System.out.println("MyInterceptor2.preHandle()");
        return true;  //继续执行action
    }
}

1、执行doDispatcher做请求分发处理里getHandler() 方法 (关键类 RequestMappingHandlerMapping )
在这里插入图片描述
mappedHandler.applyPreHandle () 执行所有拦截器的前置方法 → preHandle(),
在这里插入图片描述
在applyPreHandle()方法中,将与目标处理器关联的所有拦截器进行正序遍历,遍历执行所有拦截器的preHandle()方法
在这里插入图片描述
执行完后回到dispatch()方法继续执行,然后执行所有拦截器的后置方法
在这里插入图片描述
在这里插入图片描述
applyPostHandle()方法中,倒序遍历执行所有拦截器的postHandle()方法
在这里插入图片描述
然后执行 processDispatchResult()方法 处理模型和视图
在这里插入图片描述
进入processDispatchResult()方法中,执行render()方法进行渲染
在这里插入图片描述
渲染完后,最后在render()方法的最后,执行triggerAfterCompletion()方法
在这里插入图片描述
在triggerAfterCompletion()方法中,和前面的applyPostHandle()方法一样,这里也是倒序遍历执行拦截器的afterCompletion()方法
在这里插入图片描述

spring 拦截器与Aop

spring aop功能的继承关系图
在这里插入图片描述

MethodInterceptor是AOP项目中的拦截器(注:不是动态代理拦截器),区别与HandlerInterceptor拦截目标时请求,它拦截的目标是方法。

实现MethodInterceptor拦截器大致也分为两种:
(1)MethodInterceptor接口;
(2)利用AspectJ的注解配置;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MethodInvokeInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("before method invoke....");
        Object object = methodInvocation.proceed();
        System.out.println("after method invoke.....");
        return object;
    }
}

Aspect的注解

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AutoAspectJInterceptor {

    @Around("execution (* com.paic.phssp.springtest.controller..*.*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable{
        System.out.println("AutoAspectJInterceptor begin around......");
        Object object = point.proceed();
        System.out.println("AutoAspectJInterceptor end around......");
        return object;
    }
}

织入配置类

@Configuration
public class InterceptorConfig {
 
    public static final String traceExecution = "execution(* com.hfi.aop..*.*(..))";
 
 
    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor() {
        MethodInvokeInterceptor interceptor = new MethodInvokeInterceptor ();
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(traceExecution);
 
        // 配置增强类advisor
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setPointcut(pointcut);
        advisor.setAdvice(interceptor);
        return advisor;
    }
}

在这里插入图片描述
1.切面(Aspect):切面就是一个关注点的模块化,如事务管理、日志管理、权限管理等;

2.连接点(Joinpoint):程序执行时的某个特定的点,在Spring中就是一个方法的执行;

3.通知(Advice):通知就是在切面的某个连接点上执行的操作,也就是事务管理、日志管理等;

4.切入点(Pointcut):切入点就是描述某一类选定的连接点,也就是指定某一类要织入通知的方法;

5.目标对象(Target):就是被AOP动态代理的目标对象;

在这里插入图片描述

spring如何判断bean是否需要被代理
spring在创建完bean后,需要判断是否需要给当前bean创建代理对象。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory类中的doCreateBean方法里

try {
            this.populateBean(beanName, mbd, instanceWrapper);
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

在这里插入图片描述
进入initializeBean方法里,图上分别存在对应BeanPostProcessor的前置方法(postProcessBeforeInitialization),后置方法(postProcessAfterInitialization),然后有一个中间的初始化方法(invokeInitMethods),这个invokeInitMethods对应了实现InitializingBean的类(最前面还有个invokeAwareMethods方法,该方法可参考这篇文章aware系列接口),initializeBean方法流程如下:
在这里插入图片描述

在这里插入图片描述

然后我们再看后置方法:applyBeanPostProcessorsAfterInitialization,一直往里走该方法会调用所有BeanPostProcessor的postProcessAfterInitialization。

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;

        Object current;
        for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
            BeanPostProcessor processor = (BeanPostProcessor)var4.next();
            current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
        }

        return result;
    }

进入postProcessAfterInitialization方法:

public Object postProcessAfterInitialization(@Nullable Object bean, 
       String beanName) throws BeansException {
    if (bean != null) {
        // 获取当前bean的key:如果beanName不为空,则以beanName为key,如果为FactoryBean类型,
        // 前面还会添加&符号,如果beanName为空,则以当前bean对应的class为key
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 判断当前bean是否正在被代理,如果正在被代理则不进行封装
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            // 对当前bean进行封装
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

然后org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator就是一个BeanPostProcessor,该类的postProcessAfterInitialization会调用wrapIfNecessary方法,即该bean是否需要被包装成代理对象。是否需要代理原则就是该bean有没有与之相关的Advisor,有就代理。

spring如何查找所有Advisor源码及如何判断某个bean与之关联的Advisor有哪些

wrapIfNecessary部分源码

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && 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);//要代理的就添加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;
	}

里面的getAdvicesAndAdvisorsForBean方法就是获取拦截器方法,对应上前文说的一系列的拦截器中的advice
在这里插入图片描述
,由AbstractAdvisorAutoProxyCreator子类实现

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
        return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
    }

进入findEligibleAdvisors方法
这里首先就是获取所有切面里的Advisor,因为在bean实例化之前就解析出来了,所以这个时候一般就是直接从缓存里获取了。然后找出适用于beanClass的Advisor,然后进行扩展,会增加一个ExposeInvocationInterceptor的内部实例DefaultPointcutAdvisor,为了暴露AOP调用,以便于一些AspectJ类型的切点匹配,最后进行排序,这里的排序很重要,直接影响后面通知的方法调用顺序,然后返回。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //1. 查找所有的增强器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //2. 找到匹配当前bean的增强器
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}
 protected List<Advisor> findCandidateAdvisors() {
        Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

advisorRetrievalHelper指的是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!
            //1. 查找所有类型是Advisor接口的bean
            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) {
        //isEligibleBean(name)返回true,最终是调用AbstractAdvisorAutoProxyCreator#isEligibleAdvisorBean(name)方法 
        if (isEligibleBean(name)) {
            //如果当前增强器还没创建完,则跳过
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                try {
                    //添加Advisor
                    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;
}

实现的逻辑:

1、查找所有类型是Advisor接口的bean
2、判断当前Advisor是否正在创建,如果是则跳过,否则添加Advisor。

再接着进入前一个步骤的findAdvisorsThatCanApply方法:

protected List<Advisor> findAdvisorsThatCanApply(
        List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        //过滤已经得到的Advisors
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

AopUtils.findAdvisorsThatCanApply()实现逻辑:

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

findAdvisorsThatCanApply方法的主要功能是寻找所有Advisor(增强器)中适用于当前class的Advisor,而对于真正的匹配在canApply方法中实现。

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    if (advisor instanceof IntroductionAdvisor) {
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    //spring aop生成的增强器是InstantiationModelAwarePointcutAdvisorImpl对象,实现了PointcutAdvisor
    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;
    }
}

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

匹配规则是,先匹配类,再遍历方法是否有匹配的。canApply方法是一个短路操作,只要找到一个匹配就返回true,说明bean是需要被代理的。这里不分析spring是如何执行匹配的,阅读源码得有个度,我们只需要知道spring给我们规定的规则就好,我们切点匹配使用最多的是execution。接下来分析
execution规则
execution格式如下

//execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)

//匹配所有public修饰的方法
execution(public * *(..))
//匹配所有set开头的方法
execution(* set*(..))
//匹配AccountService接口所有的方法
execution(* com.xyz.service.AccountService.*(..))
//匹配service包下所有的方法
execution(* com.xyz.service.*.*(..))
//匹配service包以及子包所有方法
execution(* com.xyz.service..*.*(..))

再回到我们wrapIfNecessary主步骤的createProxy方法

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

    //决定对于给定的bean是否应该使用targetClass而不是它的接口代理
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    //拦截器和增强器结合
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    //设置目标类
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    //创建代理
    return proxyFactory.getProxy(getProxyClassLoader());
}

对于代理类的创建及处理,Spring委拖给了ProxyFacotry去处理,而在createProxy方法中主要是对ProxyFactory的初始化操作,进而对真正的创建代理做准备,这些初始化操作包括如下内容:
(1)获取当前类的属性

public void copyFrom(ProxyConfig other) {
    Assert.notNull(other, "Other ProxyConfig object must not be null");
    this.proxyTargetClass = other.proxyTargetClass;
    this.optimize = other.optimize;
    this.exposeProxy = other.exposeProxy;
    this.frozen = other.frozen;
    this.opaque = other.opaque;
}

(2) 决定对于给定的bean是否应该使用targetClass而不是它的接口代理,这个主要是在@EnableAspectJAutoProxy(proxyTargetClass = true)配置,如果proxyTargetClass=true,表示使用cglib代理,否则就得看代理类是否实现了接口。
(3) 结合拦截器和增强器

protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
    // Handle prototypes correctly...
    //解析拦截器,这个拦截器的值我现在还不知道怎么设置
    Advisor[] commonInterceptors = resolveInterceptorNames();

    List<Object> allInterceptors = new ArrayList<Object>();
    if (specificInterceptors != null) {
        //增强器加入到拦截器中
        allInterceptors.addAll(Arrays.asList(specificInterceptors));
        if (commonInterceptors.length > 0) {
            if (this.applyCommonInterceptorsFirst) {
                allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
            }
            else {
                allInterceptors.addAll(Arrays.asList(commonInterceptors));
            }
        }
    }
    if (logger.isDebugEnabled()) {
        int nrOfCommonInterceptors = commonInterceptors.length;
        int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
        logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
                " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
    }

    Advisor[] advisors = new Advisor[allInterceptors.size()];
    //遍历所有的拦截器,并将拦截器转换成Advisor
    for (int i = 0; i < allInterceptors.size(); i++) {
        advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
    }
    return advisors;
}

@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    //如果要封装的对象本身就是Advisor类型的那么无需再包装
    if (adviceObject instanceof Advisor) {
        return (Advisor) adviceObject;
    }
    //只能封装Advice和Advisor类型
    if (!(adviceObject instanceof Advice)) {
        throw new UnknownAdviceTypeException(adviceObject);
    }
    Advice advice = (Advice) adviceObject;
    if (advice instanceof MethodInterceptor) {
        // So well-known it doesn't even need an adapter.
        return new DefaultPointcutAdvisor(advice);
    }
    for (AdvisorAdapter adapter : this.adapters) {
        // Check that it is supported.
        if (adapter.supportsAdvice(advice)) {
            return new DefaultPointcutAdvisor(advice);
        }
    }
    throw new UnknownAdviceTypeException(advice);
}

(4) 设置目标类
(5) 进行获取代理操作
创建代理
ProxyCreatorSupport#createAopProxy

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    //创建代理
    return getAopProxyFactory().createAopProxy(this);
}

@Override
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);
        }
        //cglib动态代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        //jdk动态代理
        return new JdkDynamicAopProxy(config);
    }
}

从if中的判断条件可以看到使用cglib需要满足三个条件中的一个:

Optimize:用来控制通过CGLIB创建的代理是否使用激化的优化策略。除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于CGLIB代理,对于JDK动态代理无效。(我也没找到在哪设置)。
ProxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类的接口(直接继承目标类而不是实现目标类的接口),如果这个属性值设置为true,CGLIB代理将被创建。
hasNoUserSuppliedProxyInterfaces:是否存在代理接口.

下面对JDK与CGLIB方式的总结:

如果目标类实现了接口,默认情况下会采用JDK的动态代理实现AOP。
如果目标对象实现了接口,可以通过ProxyTargetClass强制使用CGLIB实现AOP。
如果目标对象没有实现了接口,必须采用CGLIB,Spring会自动在JDK动态代理和CGLIB之间切换。

关于动态代理更多详情可以看这篇文章动态代理详解

好的,我们要以JDK动态为例(CGLIB其实差不多一样)说明实现JDK动态代理要做两件事(new JdkDynamicAopProxy(config)):

1、实现InvocationHandler,重写invoke方法实现代理逻辑
2、使用Proxy.newProxyInstance生成代理对象

那么spring中的jdk代理是如何实现的呢?我们查看JdkDynamicAopProxy类。
JdkDynamicAopProxy实现了InvocationHandler接口。

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable

spring的代理对象通过调用AopPorxy#getProxy方法获取,而JdkDynamicAopProxy实现了AopPorxy,看下getProxy方法的实现逻辑,调用了Proxy.newProxyInstance创建代理对象。

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

再看invoke方法。

@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 {
        //equals方法的处理
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // The target does not implement the equals(Object) method itself.
            return equals(args[0]);
        }
        //hashCode方法处理
        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 dont, 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...
            //将拦截器封装在ReflectiveMethodInvocation,调用proceed方法执行拦截器链 
            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);
        }
    }
}

上面的方法中最主要的工作是创建一个拦截器链,并使用ReflectiveMethodInvocation类进行了链的封装,cglib的话他的intercept方法和jdk动态代理的invoke方法实现逻辑是一模一样,也是先封装调用链,然后逐一调用调用链,不过jdk动态代理使用的是ReflectiveMethodInvocation对象,而cglib使用的是CglibMethodInvocation。不过ReflectiveMethodInvocation和CglibMethodInvocation中的proceed方法实现逻辑是一样的。

spring aop之调用链

接前面spring aop之创建代理,我们继续分析spring是如何把Advisor(增强器)封装成调用链,并且是如何逐一调用的,这里我们以JDk动态代理为例,这块逻辑jdk和cglib是一样的。代码在JdkDynamicAopProxy#invoke方法中。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
    MethodCacheKey cacheKey = 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);
    }
    return cached;
}

getInterceptorsAndDynamicInterceptionAdvice方法只分析其中的一部分,就是把Advisor转换成MethodInterceptor。

MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
    Advice advice = advisor.getAdvice();
    //通知本身就是MethodInterceptor对象,就不需要再转换
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }
    //如果通知不是MethodInterceptor对象对象,使用适配器转换
    for (AdvisorAdapter adapter : this.adapters) {
        if (adapter.supportsAdvice(advice)) {
            interceptors.add(adapter.getInterceptor(advisor));
        }
    }
    if (interceptors.isEmpty()) {
        throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}

adapters对象有三个值

private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
public DefaultAdvisorAdapterRegistry() {
    //对前置通知的代理
    registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
    //返回通知代理
    registerAdvisorAdapter(new AfterReturningAdviceAdapter());
    //异常通知代理
    registerAdvisorAdapter(new ThrowsAdviceAdapter());
}

这里以MethodBeforeAdviceAdapter作为例子分析

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {
        return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }

}

MethodBeforeAdviceAdapter把前置通知转换成MethodBeforeAdviceInterceptor对象。
所以我们再来看下几种通知的类图:
在这里插入图片描述
从类图可以看出
AspectJAfterAdvice、AspectJAfterThrowingAdvice、AspectJAroundAdvice是实现了MethodInterceptor接口,AspectJMethodBeforeAdvice和AspectJAfterReturningAdvice是需要使用适配器适配,才能生成MethodInterceptor对象。
把拦截器生成MethodInterceptor拦截器链后,接下来又如何去调用呢?这个逻辑在ReflectiveMethodInvocation的proceed()上。

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

    //增加计数器,得到下一个通知或者拦截器
    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);
    }
}

在proceed方法中,或许代码逻辑并没有我们想象的那么复杂,ReflectiveMethodInvocation中的主要职责是维护了链接调用的计数器,记录着当前调用链接的位置,以便链接可以有序地进行下去,在这个方法中并没有维护调用链的顺序,而是将此工作委拖给各个增强器,在各个增强器的内部进行逻辑实现。
我们再来分析MethodBeforeAdviceInterceptor和AspectJAfterAdvice执行逻辑。

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
    private MethodBeforeAdvice advice;
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        return mi.proceed();
    }
}

@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
    invokeAdviceMethod(getJoinPointMatch(), null, null);
}

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
    Object[] actualArgs = args;
    if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
        actualArgs = null;
    }
    try {
        ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
        // TODO AopUtils.invokeJoinpointUsingReflection
        //调用通知的方法
        return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
    }
    catch (IllegalArgumentException ex) {
        throw new AopInvocationException("Mismatch on arguments to advice method [" +
                this.aspectJAdviceMethod + "]; pointcut expression [" +
                this.pointcut.getPointcutExpression() + "]", ex);
    }
    catch (InvocationTargetException ex) {
        throw ex.getTargetException();
    }
}

MethodBeforeAdviceInterceptor的invoke方法是调用了前置通知的before方法,前置通知before通过反射调用通知方法,然后再调用proceed()执行调用链。

最后补充Advisor类的类架构

Advisor类架构

在这里插入图片描述

aopalliance定义了AOP的通知Advice和连接点Joinpoint接口,并且还有继承上述接口的MethodInterceptor和MethodInvocation。这两个类相信大家都很熟悉。

然后我们来看一下Spring AOP中Advisor相关的类图。Advisor是Spring AOP独有的概念,比较重要的类有AbstractPointcutAdvisor和InstantiationModelAwarePointcutAdvisor。相关的讲解都在图中表明了,如果这张图中的概念和类同学们都熟识,那么对AOP的了解就已经很深入了。
在这里插入图片描述
更加详细的类架构问题可以参考这篇文章Spring AOP(三) Advisor类架构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值