Spring之AOP

(一)AOP相关介绍:

1. AOP概念

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程.

作用:在不修改目标类代码的前提下,可以通过AOP技术去增强目标类的功能。通过【预编译式】或者【运行期动态代理】实现程序功能的统一维护的一种技术. 而达到对目标类进行无感知的功能增强. 因此在项目开发中,我们可以利用AOP, 对业务代码中【业务逻辑】和【系统逻辑】进行隔离,从而使得【业务逻辑】和【系统逻辑】之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

为什么使用AOP?AOP采取横向抽取机制,补充了 传统纵向继承体系(OOP)无法解决的重复性代码优化(性能监视、事务管理、安全检查、缓存),将业务逻辑和系统处理的代码(关闭连接、事务管理、操作日志记录)解耦。

AOP与纵向继承:

优势:
重复性代码被抽取出来之后,维护更加方便.
不想修改原有代码前提下,可以动态横向添加共性代码

 1.2 AOP相关术语:

命名 定义
Joinpoint(连接点) 所谓连接点是指被增强的方法.
Pointcut(切入点) 要对哪些Jointpoint进行拦截的定义.
Advice(通知/增强)

拦截到Jointpoint之后所要做的事情,也就是具体进行增强的内容. 通知分为前置通知,后置通知,异常通知,最终通知,

环绕通知.(切面要完成的功能)

Introdtion(引介)

引介是一种特殊的通知,在不修改类代码的前提下,Introduction可以在运行期为类动态地增加一些方法或Field.

Target(目标对象)

代理的实际目标对象

Weaving(织入)

把增强应用到目标对象来创建新的代理对象的过程。

Proxy(代理)

一个类被AOP织入增强后就产生一个结果代理类。

切面(Aspect) 切入点和通知的结合(pointCut与Around)。
Advisor(通知器或者顾问) 和切面相似。

 

1.3 Spring AOP原理:

SpringAop共分为四个阶段: 创建代理对象, 拦截目标对象, 调用代理对象, 调用目标对象
创建代理对象: 在Spring中,通过getBean方法创建Bean实例,在创建完实例之后, Spring容器根据AOP的配置去匹配目标类的类名,如果目标类满足切面规则,则会调用ProxyFactory,根据目标对象自动选择不同的代理策略(JDK Proxy与CglibProxy),创建代理Bean并缓存到IOC容器.。
拦截目标对象: 当用户调用目标对象的某个方法时, 将会被一个叫做AopProxy的对象拦截, AopProxy的getProxy()方法会返回JdkDynamicAopProxy或者CglibAopProxy。Spring将所有的调用策略封装到了这两个对象中, 它们实现了InvocationHandler接口, 在这个接口的invoke方法中,会触发MethodInvocation的Proceed方法, 随后按顺序执行所有符合APO拦截器规则的拦截器链.
调用代理对象: SpringAOP拦截器链中的每个元素被命名为MethodInterceptor(切面配置中的Advice通知). MethodInterceptor.invoke方法执行织入部分的代码
调用目标对象:当currentInterceptorIndex==interceptorsAndDynamicMethodMatchers.size() - 1  然后调用invokeJoinpoint方法完成对目标方法的调用

目标对象到代理对象的创建过程:

(二)代理:

静态代理与动态代理:

静态代理的作用:为其他对象提供一种代理以控制对这个对象的访问。另一种情况是,有时一个客户不想或者不能直接引用另外一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

2.1 JDK动态代理:

JDK动态代理是这样一种class: 在运行时生成class,在生成它时我们必须提供一组interface给它,然后该class就会声明它实现了这些interface。因此我们可以将该class的实例当作这些interface中的任何一个来用。当然,这个动态代理其实就是一个proxy,它不会替我们实质性的工作,在生成它的实例时我们必须提供一个handler,由它接管实际的工作。

JDK动态代理:Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类(接口):

(1)Interface InvocationHandler:该接口定义了一个方法public object invoke(Object obj, Method method, Object[] args) 在实际使用时第一个object一般是指代理类,method是被代理的方法,args为该方法的参数数组,这个抽象方法在代理类中动态实现。

(2)Proxy:该类即为动态代理类,其中主要包括以下内容:

static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) , 通过该方法返回代理类的一个实例,返回后的代理实例可以当作代理类来使用。

JDK动态代理创建步骤:

  1. 创建一个接口Invocation Handler的类,它必须实现invoke方法

  2. 创建被代理的类及接口

  3. 通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)创建一个代理

  4. 通过代理调用方法

JDK动态代理代码实现:

public interface Subject {
    void myNewRequest();
}

目标类:

public class RealSubject implements Subject{
    @Override
    public void myNewRequest() {
        System.out.println("new request from realSubject");
    }
}

代理增强类:

复制代码
public class DynamicSubjectInvocationHandler implements InvocationHandler {
    private Object sub;
    public DynamicSubjectInvocationHandler(Object sub){
        this.sub = sub;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy: "+ proxy.getClass());
        System.out.println("before:"+method);
        method.invoke(sub,args);
        System.out.println("after:"+method);
        return null;
    }
}
复制代码

客户端:

复制代码
public class DynamicProxyClient {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        InvocationHandler invocationHandler = new DynamicSubjectInvocationHandler(realSubject);
        Class<?> classType = invocationHandler.getClass();
        /*
         If the proxy class defined by the given loader implementing
         the given interfaces exists, this will simply return the cached copy;
         otherwise, it will create the proxy class via the ProxyClassFactory
         */
        Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(),
                realSubject.getClass().getInterfaces(),invocationHandler);
        subject.myNewRequest();
    }
复制代码

测试结果:

proxy: class com.sun.proxy.$Proxy0

before:public abstract void com.spring.dynamicProxy.Subject.myNewRequest()

new request from realSubject

after:public abstract void com.spring.dynamicProxy.Subject.myNewRequest()

2.2 Cglib动态代理:

CGLIB:目标对象没有实现接口的功能,无法通过JDK动态代理实现,这个时候可以创建目标对象的子类对象,在子类对象中重写目标对象的方法,以此来完成功能的增强。

代码实现:

public class RealSubject {
    public void myNewRequest() {
        System.out.println("new request from realSubject");
    }
}

获取代理类的实现:

复制代码
public class MyProxyUtils {
    public static RealSubject getProxy(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                if("myNewRequest".equalsIgnoreCase(method.getName())){
                    System.out.println("前置增强");
                }
                return methodProxy.invokeSuper(o,objects);
            }
        });
        RealSubject proxy = (RealSubject) enhancer.create();
        return proxy;
    }
}
复制代码

测试代码:

public class client {
    public static void main(String[] args) {
        RealSubject proxy = MyProxyUtils.getProxy();
        proxy.myNewRequest();
    }
}

测试结果:

前置增强

new request from realSubject

 2.3 JDK动态代理和Cglib动态代理的区别

1.JDK动态代理是Java自带的,cglib动态代理是第三方jar包提供的

2.JDK动态代理是针对【拥有接口的目标类】进行动态代理的,Cglib是【对父类的方法进行覆盖,非final类】都可以进行动态代理。但是Spring优先使用JDK动态代理。

3.JDK动态代理实现的逻辑是目标类和代理类都实现同一个接口,目标类和代理类是平级的而Cglib动态代理实现的逻辑是给目标类生个孩子(子类,也就是代理类),目标类和代理类是父子关系

4.JDK动态代理在早期的JDK1.6左右性能比cglib差,但是在JDK1.8以后cglib和jdk的动态代理性能基本上差不多。甚至jdk动态代理性能更加的优越。

JDK动态代理是通过Proxy的newProxyInstance方法返回代理对象,通过InvocationHandler的实现类,重写invoke方法,完成对目标类接口的增强。
cglib动态代理是使用enhancer,对目标类的拦截主要封装在了enhancer的setCallBack回调方法中,该方法的有一个参数methodInterceptor,该参数通过重写intercept方法以此对目标方法进行拦截与增强。

(三)AOP原理

3.1 AOP运行样例

定义切面:
复制代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Aspect
public class SimpleAspect {
    // 定义切入点表达式
    @Pointcut("execution(* com.gzz.spring.aspectJ.UserServiceImpl.*(..))")
    private void pointcut(){
    }

    // 前置通知
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的前置通知(@Before)...");
    }

    // 后置通知
    @After("pointcut()")
    public void after(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的后置通知(@After)...");
    }

    // 环绕通知
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws InterruptedException {
        String methodName = proceedingJoinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的环绕通知前(@Around)...");
        try {
            long startTime = System.currentTimeMillis();
            Object result = proceedingJoinPoint.proceed();
            long endTime = System.currentTimeMillis();
            System.out.println(methodName + "()方法耗时: " + (endTime - startTime) + "毫秒"+"; 环绕通知后(@Around)...");
            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null;
        }
    }

    // 返回通知
    @AfterReturning("pointcut()")
    public void afterReturning(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的后置返回通知(@AfterReturning)...");
    }

    @AfterThrowing("pointcut()")
    public void afterThrowing(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的后置返回通知(@afterThrowing)...");
    }
}
复制代码
定义目标接口
public interface UserService {
    public void addUser();
}

定义目标对象:

复制代码
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;

@Component
public class UserServiceImpl implements UserService{
    @Override
    public void addUser() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("新增用户...");
    }
}
复制代码

定义配置类:

复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.gzz")
public class SpringConfiguration {

    public SpringConfiguration() {
        System.out.println("spring 容器启动");
    }

    @Bean
    public SimpleAspect simpleAspect(){
        return new SimpleAspect();
    }

    @Bean
    public UserService userService(){
        return new UserServiceImpl();
    }
}
复制代码

测试:

复制代码
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringConfigurationTest {
    @Test
    public void test1(){
        //创建纯注解方式的spring 容器
        ApplicationContext applicationContext  = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.addUser();
    }
}
复制代码
结果输出:
如果addUser正常执行:  打印如下
如果addUser异常执行,打印如下:
spring5的几种通知的执行顺序:
程序执行正常:
1、环绕通知前
2、@Before通知
3、程序逻辑
4、@AfterReturning通知
5、@After通知
6、环绕通知后
程序执行异常:

 

1、环绕通知前
2、@Before通知
3、@AfterThrowing异常通知
4、@After通知
异常日志

3.2 AOP创建流程

AbstractAutowireCapableBeanFactory调用applyBeanPostProcessorsAfterInitialization方法创建AOP代理对象:
复制代码
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      //调用aware接口
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      //应用BeanPostProcessor的postProcessBeforeInitialization方法
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      //执行初始化方法(先调用InitializingBean的afterPropertiesSet,再调用init-method属性指定的初始化方法)
      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()) {
      //应用BeanPostProcessor的postProcessAfterInitialization方法(AOP代理对象生成)
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}
复制代码
复制代码
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
   Object result = existingBean;
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}
复制代码

AbstractAutoProxyCreator:

复制代码
@Override
public Object postProcessAfterInitialization(@Nullable 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 (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
   }
   // Advice/Pointcut/Advisor/AopInfrastructureBean接口的beanClass不进行代理以及对beanName为aop内的切面名也不进行代理
   // 此处可查看子类复写的shouldSkip()方法
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // Create proxy if we have advice.
   // 查找对代理类相关的advisor对象集合,此处就与ponit-cut表达式有关了
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

   // 对相应的advisor不为空才采取代理
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      // 通过jdk动态代理或者cglib动态代理,产生代理对象
      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;
}
复制代码

AbstractAdvisorAutoProxyCreator:

复制代码
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
      Class<?> beanClass, String beanName, @Nullable 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) {
   // 候选的Advisors
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   // 合格的Advisors
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      //排完序就决定了通知的执行先后顺序
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}
复制代码
复制代码

protected
Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } // 创建代理工厂对象 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); //如果没有使用CGLib代理 if (!proxyFactory.isProxyTargetClass()) { // 是否可能使用CGLib代理 if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { // 查看beanClass对应的类是否含有InitializingBean.class/DisposableBean.class/Aware.class接口 // 无则采用JDK动态代理,有则采用CGLib动态代理 evaluateProxyInterfaces(beanClass, proxyFactory); } } // 获得所有关联的Advisor集合(该分支待补充) Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); // 此处的targetSource一般为SingletonTargetSource proxyFactory.setTargetSource(targetSource); // 空的实现 customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); // 是否设置预过滤模式,此处针对本文为true if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 获取使用JDK动态代理或者cglib动态代理产生的对象 return proxyFactory.getProxy(getProxyClassLoader()); }protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } // 创建代理工厂对象 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); //如果没有使用CGLib代理 if (!proxyFactory.isProxyTargetClass()) { // 是否可能使用CGLib代理 if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { // 查看beanClass对应的类是否含有InitializingBean.class/DisposableBean.class/Aware.class接口 // 无则采用JDK动态代理,有则采用CGLib动态代理 evaluateProxyInterfaces(beanClass, proxyFactory); } } // 获得所有关联的Advisor集合(该分支待补充) Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); // 此处的targetSource一般为SingletonTargetSource proxyFactory.setTargetSource(targetSource); // 空的实现 customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); // 是否设置预过滤模式,此处针对本文为true if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 获取使用JDK动态代理或者cglib动态代理产生的对象 return proxyFactory.getProxy(getProxyClassLoader()); }
复制代码

 

Aop创建代理流程图:

总结:

在AbstractAutoWireCapableBeanFactory的initializeBean方法中,调用applyBeanPostProcessorAfterInitialization方法,进而调用beanProcessor的postProcessAfterInitialization方法,该钩子方法调用AbtsractAutoProxyCreator的wrapIfNecessary进行创建代理。wrapIfNecessary方法中会通过getAdvicesAndAdvisorsForBean方法查找到所有的advisors并进行排序.  具体查找的过程利用pointcut进行匹配。之后通过ProxyFactory创建代理,具体创建代理的策略有JDK动态代理与CGLIB动态代理。

3.3 AOP执行流程

复制代码
// org.springframework.aop.framework.JdkDynamicAopProxy.invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
 
    // 1.获取到目标对象,也就是被代理对象的引用
    TargetSource targetSource = this.advised.targetSource;
    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();
        }
        // 如果方法是DecoratingProxy类型,也不需要拦截器执行
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        // 如果是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;
 
        // 2. 如果exposeProxy属性值为true,则将代理对象暴露到ThreadLocal中
        // exposeProxy是通过注解@EnableAspectJAutoProxy(exposeProxy = true)进行指定的,如果配置为true,
        // 则可以使用AopContext.currentProxy()获取到代理对象. 在Spring事务方法自调用的时候经常使用到.
        if (this.advised.exposeProxy) {
            // 将代理对象暴露到ThreadLocal中
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
 
        // 3.获得目标对象实例
        target = targetSource.getTarget();
 
        // 获取目标对象的类型
        Class<?> targetClass = (target != null ? target.getClass() : null);
 
        // 4.获得目标方法对应的拦截器链
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
 
        // 5.如果对应的拦截器链为空,也就是没有可以应用到此方法的通知(Interceptor),则直接通过反射方式进行调用 ==> method.invoke(target, args)
        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 {
            // 6.如果拦截器链不为空,则需要创建一个MethodInvocation(方法调用对象)
            MethodInvocation invocation =
                new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // 调用其proceed方法,实际上是调用ReflectiveMethodInvocation.proceed()方法
            retVal = invocation.proceed();
        }
 
        // 7.必要时转换返回值
        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.
 
            // 恢复ThreadLocal中的旧代理对象
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}
复制代码

获取拦截器链:

复制代码
// org.springframework.aop.framework.AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    // 1、首先从缓存中查找是否存在拦截器链
    //        private transient Map<MethodCacheKey, List<Object>> methodCache;  存放方法Method ==> 拦截器链集合的对应关系
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
        // 2、如果缓存中不存在拦截器链,则委托getInterceptorsAndDynamicInterceptionAdvice()方法继续查找
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
        // 3、将前面一个步骤找到的拦截器链存入缓存中
        this.methodCache.put(cacheKey, cached);
    }
    // 4、如果缓存中存在拦截器链的话,则直接返回
    return cached;
}
复制代码
委托给advisorChainFactory查找:
复制代码
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
    Advised config, Method method, @Nullable Class<?> targetClass) {
 
    // This is somewhat tricky... We have to process introductions first,
    // but we need to preserve order in the ultimate list.
 
    // 使用单例模式创建DefaultAdvisorAdapterRegistry实例
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
 
    // 从config中获取所有的advisors增强器
    Advisor[] advisors = config.getAdvisors();
 
    // 保存拦截器集合,长度就是增强器的总数量
    List<Object> interceptorList = new ArrayList<>(advisors.length);
 
    // 目标类
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
 
    // 判断是否包含IntroductionAdvisor类型的增强器
    Boolean hasIntroductions = null;
 
    // 遍历advisors数组,根据不同类型的Advisor做不同的处理
    for (Advisor advisor : advisors) {
        // 如果advisor是PointcutAdvisor类型,判断advisor能否应用到目标方法
        if (advisor instanceof PointcutAdvisor) {
            // Add it conditionally.
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                // 检查当前advisor的pointcut是否可以匹配当前方法
                boolean match;
                if (mm instanceof IntroductionAwareMethodMatcher) {
                    if (hasIntroductions == null) {
                        hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                    }
                    match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                } else {
                    match = mm.matches(method, actualClass);
                }
                // 如果匹配的话,将增强器转换成MethodInterceptor拦截器对象
                if (match) {
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    if (mm.isRuntime()) {
                        // Creating a new object instance in the getInterceptors() method
                        // isn't a problem as we normally cache created chains.
                        for (MethodInterceptor interceptor : interceptors) {
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        // 如果advisor是IntroductionAdvisor类型,判断advisor能否应用到目标类
        else if (advisor instanceof IntroductionAdvisor) {
            IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
            if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        else {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }
 
    return interceptorList;
}
复制代码

将增强器转换成MethodInterceptor拦截器对象:

复制代码
//DefaultAdvisorAdapterRegistry#getInterceptors()方法:
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<>(3);
    Advice advice = advisor.getAdvice();
    // 如果是MethodInterceptor类型的通知,则直接加入集合中
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }
    
    // 通过适配器将advisor转换为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[0]);
}
复制代码

执行拦截器与目标方法:

复制代码
// ReflectiveMethodInvocation.proceed()
// 开始执行拦截器链增强方法
public Object proceed() throws Throwable {
    // We start with an index of -1 and increment early.
 
    // 1.当前拦截器下标:从-1的位置开始, 直到满足索引下标 =(拦截器的长度  -1)的条件(所有拦截器都执行完毕),此时需要执行目标方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        // 执行目标方法
        return invokeJoinpoint();
    }
 
    // 2.每次调用时,将索引的值递增,从拦截器链中获取下一个需要执行的拦截器
    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;
        // 目标类所属类型
        Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
 
        // 动态匹配,判断运行时参数是否匹配
        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
            // 如果匹配成功,则执行当前拦截器逻辑
            return dm.interceptor.invoke(this);
        } else {
            // 如果匹配失败,则会跳过当前拦截器interceptor,则会调用proceed()方法执行拦截器链中的下一个拦截器的处理
            return proceed();
        }
 
    } else {
        // It's an interceptor, so we just invoke it: The pointcut will have
        // been evaluated statically before this object was constructed.
 
        // 3.只是一个普通的拦截器,则触发拦截器链责任链的调用,并且参数为ReflectiveMethodInvocation本身
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}
复制代码

aop执行流程图:

 
总结:
当目标对象的某个方法被调用时,会被AopProxy拦截,该对象实现了InvocationHandler接口,在该接口的invoke方法中,首先会去获取拦截器链,也就是把与pointcut匹配的所有advisor封装成methodInterceptor对象进行返回。之后判断拦截器是否为空,如果为空则直接调用目标方法,否则创建MethodInvocation对象,调用其proceed方法,在该方法中,逐个调用MethodInterceptor的invoke方法。直到所有的拦截器已经执行,最后调用目标类的方法。
 
ReflectiveMethodInnocation的proceed()方法的执行流程大体如下:
判断是否所有的拦截器已经执行完成,从-1(当前拦截器下标)的位置开始, 直到满足索引下标 =(拦截器的长度 -1)的条件(即所有拦截器都执行完毕)也就是0-1 =- 1,此时需要执行目标方法(在本例中就是执行addUser()方法);
每次调用时,将索引的值递增,从拦截器链中获取下一个需要执行的拦截器;
posted @   小兵要进步  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

侧边栏
点击右上角即可分享
微信分享提示