• SpringAOP执行流程——从源码画流程图





    重点在ProxyFactory代理对象执行过程和@EnableAspectJAutoProxy执行过程



    了解ProxyFactory

    入门操作

    我现在创建了几个Advice

    public class HushangAfterReturningAdvice implements AfterReturningAdvice {
    
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            System.out.println("方法return后执行");
        }
    }
    
    public class HushangAroundAdvice implements MethodInterceptor {
    
        @Nullable
        @Override
        public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
            System.out.println("方法执行Around前");
            Object proceed = invocation.proceed();
            System.out.println("方法执行Around后");
            return proceed;
        }
    }
    
    public class HushangBeforeAdvice implements MethodBeforeAdvice {
    
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("方法执行前执行");
        }
    }
    
    public class HushangThrowsAdvice implements ThrowsAdvice {
    
        public void afterThrowing(Method method, Object[] args, Object target, NullPointerException ex) {
            System.out.println("方法抛出异常后执行");
        }
    
    }
    

    接下来有一个UserService的类作为target目标方法

    public class UserService {
    
       public void test(){
          System.out.println("test()...");
       }
    
    }
    

    接下来就是一个测试类

    public class Test {
    
        public static void main(String[] args) {
    		
            UserService target = new UserService();
            ProxyFactory proxyFactory = new ProxyFactory();
            // 如果不设置target,那么下面的getProxy()方法进行强制转换就会报错
            proxyFactory.setTarget(target);
            // 这里添加一个beforeAdvice
            proxyFactory.addAdvice(new HushangBeforeAdvice());
    
            UserService proxy = (UserService) proxyFactory.getProxy();
            proxy.test();
        }
    }
    

    现在的程序运行结果就是

    方法执行前执行
    test()...
    
    Process finished with exit code 0
    



    添加多个Advice的执行顺序

    添加多个Advice,进而查看执行顺序

    public class Test {
    
        public static void main(String[] args) {
    
    
            UserService target = new UserService();
            ProxyFactory proxyFactory = new ProxyFactory();
            // 如果不设置target,那么下面的getProxy()方法进行强制转换就会报错
            proxyFactory.setTarget(target);
            // 我添加了三个Advice 根据我添加Advice的顺序执行的相应的增强方法
            proxyFactory.addAdvice(new HushangAroundAdvice());
            proxyFactory.addAdvice(new HushangBeforeAdvice());
            proxyFactory.addAdvice(new HushangAroundAdvice());
    
            UserService proxy = (UserService) proxyFactory.getProxy();
            proxy.test();
        }
    }
    

    此时输出结果是

    方法执行Around前
    方法执行前执行
    方法执行Around前
    test()...
    方法执行Around后
    方法执行Around后
    
    Process finished with exit code 0
    



    关于异常Advice

    从下面的代码可以发现,ThrowsAdvice接口中没有需要必须重写的方法,而下面这个方法是我自己写的。

    public class HushangThrowsAdvice implements ThrowsAdvice {
    
       public void afterThrowing(Method method, Object[] args, Object target, NullPointerException ex) {
          System.out.println("方法抛出异常后执行");
       }
    
    }
    

    其实在ThrowsAdvice接口中的注释有规定我们应该在实现类中定义什么样子的代码

    在这里插入图片描述

    在底层源码中就是先校验我们的类型是否为ThrowsAdvice接口,然后在去调用对应的afterThrowing()方法



    关于proceed()方法

    首先我们可以看到我这里定义的AroundAdvice,在方法中我自己还调用了invocation.proceed();此方法,明明其他几个Advice都不需要我额外多调用方法,直接写相应的增强逻辑就行了。

    public class HushangAroundAdvice implements MethodInterceptor {
    
       @Nullable
       @Override
       public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
          System.out.println("方法执行Around前");
          Object proceed = invocation.proceed();
          System.out.println("方法执行Around后");
          return proceed;
       }
    }
    

    其实我们往ProxyFactory中添加的多个Advice,它底层源码就是调用的proceed()方法,如果我们这里不显示的调用,那么整个调用链路就断了。

    比如我现在将调用proceed()方法这行注释掉,然后再去进行测试

    public class HushangAroundAdvice implements MethodInterceptor {
    
       @Nullable
       @Override
       public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
          System.out.println("方法执行Around前");
           // 我现在将下面这行注释掉
          //Object proceed = invocation.proceed();
          System.out.println("方法执行Around后");
          return proceed;
       }
    }
    
    public class Test {
        public static void main(String[] args) {
    
            UserService target = new UserService();
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(target);
            
            proxyFactory.addAdvice(new HushangBeforeAdvice());
            proxyFactory.addAdvice(new HushangAroundAdvice()); // 直接从这里断开了
            proxyFactory.addAdvice(new HushangBeforeAdvice());
            proxyFactory.addAdvice(new HushangAroundAdvice());
    
            UserService proxy = (UserService) proxyFactory.getProxy();
            proxy.test();
        }
    }
    

    此时的输出结果就是

    方法执行前执行
    方法执行Around前
    方法执行Around后
    
    Process finished with exit code 0
    



    指定方法才进行增强逻辑

    现在UserService类中有两个方法,我想要特定的方法才去执行Advice的增强,其他方法调用时不去进行增强

    public class UserService {
    
       public void test(){
          System.out.println("test()...");
       }
       
       public void a(){
          System.out.println("a()...");
       }
    
    }
    

    我们可以使用Advisor来实现满足指定条件的方法才能进行Advice相关的增强。

    public class Test {
        public static void main(String[] args) {
    
            UserService target = new UserService();
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(target);
            // proxyFactory.addAdvice(new HushangBeforeAdvice());
    
            // 我们可以理解为 Advisor = Pointcut + Advice
            proxyFactory.addAdvisor(new PointcutAdvisor() {
                @Override
                public Pointcut getPointcut() {
                    // 在这里使用Pointcut对象来进行判断 哪些对象能进行增强
                    return new StaticMethodMatcherPointcut() {
                        @Override
                        public boolean matches(Method method, Class<?> targetClass) {
                            // 判断方法名是否为test
                            return method.getName().equals("test");
                        }
                    };
                }
    
                @Override
                public Advice getAdvice() {
                    // 上面的Pointcut校验满足后,才会执行该Advice
                    return new HushangBeforeAdvice();
                }
    
                // 次方法不用管
                @Override
                public boolean isPerInstance() {
                    return false;
                }
            });
    
            UserService proxy = (UserService) proxyFactory.getProxy();
            proxy.test();
        }
    }
    



    创建代理对象的其他方式

    接下来我们希望ProxyFactory所产生的代理对象能直接就是Bean,能直接从Spring容器中得到UserSerivce的代理对象



    ProxyFactoryBean

    在配置类中创建一个bean

    // 这里的具体使用和上面直接使用ProxyFactory差不多
    // 添加一个beanName为userService  Type为ProxyFactoryBean的对象
    @Bean
    public ProxyFactoryBean userService(){
       UserService userService = new UserService();
       ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        // 指定目标类
       proxyFactoryBean.setTarget(userService);
        // 添加Advice
       proxyFactoryBean.addAdvice(new HushangAroundAdvice());
       return proxyFactoryBean;
    }
    

    启动类:

    public class Test {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    
            UserService userService = (UserService) context.getBean("userService");
            userService.test();
        }
    }
    

    输出结果为

    方法执行Around前
    test()...
    方法执行Around后
    
    Process finished with exit code 0
    



    BeanNameAutoProxyCreator

    它的实现是基于BeanPostProcessor来实现的

    我现在在UserService和HushangAroundAdvice两个类上面都添加了@Component注解,让他们两个都是一个bean。

    现在通过指定某个bean的名字,来对该bean进行代理

    @Bean
    public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
       BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
       beanNameAutoProxyCreator.setBeanNames("userSe*");
       beanNameAutoProxyCreator.setInterceptorNames("hushangAroundAdvice");
    
       return beanNameAutoProxyCreator;
    }
    

    现在也实现了动态代理的功能

    启动类:

    public class Test {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    
            UserService userService = (UserService) context.getBean("userService");
            userService.test();
        }
    }
    

    输出结果为

    方法执行Around前
    test()...
    方法执行Around后
    
    Process finished with exit code 0
    



    DefaultAdvisorAutoProxyCreator

    DefaultAdvisorAutoProxyCreator它就是一个BeanPostProcessor。它会在实例化后调用,每次创建bean时,它会获取Spring容器中所有的Advisor,在其中的pointcut和我当前创建的bean是否匹配。如果匹配上就表示当前创建的bean需要动态代理,代理的逻辑就是Advisor中的Advice

    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor(){
        // 创建一个pointcut
        NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
        pointcut.addMethodName("test");
    
        DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
        // 使用上面创建的pointcut
        defaultPointcutAdvisor.setPointcut(pointcut);
        // 指定Advice
        defaultPointcutAdvisor.setAdvice(new HushangAroundAdvice());
    
        return defaultPointcutAdvisor;
    }
    
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    
        return defaultAdvisorAutoProxyCreator;
    }
    

    其实对上面的代码进行一个优化,使用@Import注解直接导入DefaultAdvisorAutoProxyCreator

    @ComponentScan("com.zhouyu")
    @Configuration
    @Import(DefaultAdvisorAutoProxyCreator.class)
    public class AppConfig {
    
    	@Bean
    	public DefaultPointcutAdvisor defaultPointcutAdvisor(){
    		// 创建一个pointcut
    		NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
    		pointcut.addMethodName("test");
    
    		DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
    		// 使用上面创建的pointcut
    		defaultPointcutAdvisor.setPointcut(pointcut);
    		// 指定Advice
    		defaultPointcutAdvisor.setAdvice(new HushangAroundAdvice());
    
    		return defaultPointcutAdvisor;
    	}
    }
    

    其实现在上面就是做了两件事:要和那些bean的方法进行匹配,匹配后要进行的增强逻辑是什么

    而我们使用注解的方式其实也就是做的这两件事。

    我们现在的动态代理其实就是用到的:ProxyFactory、Advisor、pointcut、Advice



    对SpringAOP的理解

    Spring的用法

    @Aspect
    @Component
    public class HushangAspect {
    
    	@Before("execution(public void com.zhouyu.service.UserService.test())")
    	public void husahngBefore(JoinPoint joinPoint){
    		System.out.println("before...");
    	}
    
    }
    

    切点表达式就是Pointcut、注解+方法就是Advice、这一整个就是Advisor

    @ComponentScan("com.zhouyu")
    @Configuration
    @EnableAspectJAutoProxy
    public class AppConfig {
        ...
    }
    

    通过查看@EnableAspectJAutoProxy注解的源码,它其实就是往Spring容器中添加一个AnnotationAwareAspectJAutoProxyCreator对象,它是InstantiationAwareBeanPostProcessor类型的,

    AnnotationAwareAspectJAutoProxyCreator对象它就是去解析我们的切面类、切点表达式、增强



    TargetSource

    在我们日常的AOP中,被代理对象就是Bean对象,是由BeanFactory给我们创建出来的,但是Spring AOP中提供了TargetSource机制,可以让我们用来自定义逻辑来创建被代理对象。

    public class Test {
        public static void main(String[] args) {
    
            UserService target = new UserService();
            ProxyFactory proxyFactory = new ProxyFactory();
            
            // 之前直接设置target的方式,其实该方法的底层会把我们这里设置的target包装成一个TargetSource对象
            // proxyFactory.setTarget(target);
            proxyFactory.setTargetSource(new TargetSource() {
                @Override
                public Class<?> getTargetClass() {
                    return null;
                }
    
                @Override
                public boolean isStatic() {
                    return false;
                }
    
                @Override
                public Object getTarget() throws Exception {
                    // 我们可以在此方法中自定义逻辑,来创建被代理对象
                    // 当代理对象执行某个方法之前就会调用getTarget()方法,获取被代理对象
                    return null;
                }
    
                @Override
                public void releaseTarget(Object target) throws Exception {
    
                }
            });
    
    
            proxyFactory.addAdvice(new HushangBeforeAdvice());
            proxyFactory.addAdvice(new HushangAroundAdvice());
    
            UserService proxy = (UserService) proxyFactory.getProxy();
            proxy.test();
        }
    }
    

    比如之前所提到的@Lazy注解,当加在属性上时,会产生一个代理对象赋值给这个属性,产生代理对象的代码为:

    protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
        BeanFactory beanFactory = getBeanFactory();
        Assert.state(beanFactory instanceof DefaultListableBeanFactory,"BeanFactory needs to be a DefaultListableBeanFactory");
        final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
    
        TargetSource ts = new TargetSource() {
            @Override
            public Class<?> getTargetClass() {
                return descriptor.getDependencyType();
            }
            @Override
            public boolean isStatic() {
                return false;
            }
            @Override
            public Object getTarget() {
                Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
                // 依赖注入的方法 根据type找对象
                Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
                if (target == null) {
                    Class<?> type = getTargetClass();
                    if (Map.class == type) {
                        return Collections.emptyMap();
                    }
                    else if (List.class == type) {
                        return Collections.emptyList();
                    }
                    else if (Set.class == type || Collection.class == type) {
                        return Collections.emptySet();
                    }
                    throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
                                                            "Optional dependency not present for lazy injection point");
                }
                if (autowiredBeanNames != null) {
                    for (String autowiredBeanName : autowiredBeanNames) {
                        if (dlbf.containsBean(autowiredBeanName)) {
                            dlbf.registerDependentBean(autowiredBeanName, beanName);
                        }
                    }
                }
                return target;
            }
            @Override
            public void releaseTarget(Object target) {
            }
        };
    
        // 在为ProxyFactory设置一个TargetSource
        ProxyFactory pf = new ProxyFactory();
        pf.setTargetSource(ts);
        Class<?> dependencyType = descriptor.getDependencyType();
        if (dependencyType.isInterface()) {
            pf.addInterface(dependencyType);
        }
        // 再返回ProxyFactory创建的代理对象
        return pf.getProxy(dlbf.getBeanClassLoader());
    }
    



    ProxyFactory选择JDK/CJLIB代理

    ProxyFactory的简单使用案例如下

    public class Test {
        public static void main(String[] args) {
    
            UserService target = new UserService();
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(target);
            
            proxyFactory.addAdvice(new HushangBeforeAdvice());
            proxyFactory.addAdvice(new HushangAroundAdvice());
            
            // 我们还可以为ProxyFactory设定一些其他的值
            proxyFactory.setOptimize(true);
    		proxyFactory.setProxyTargetClass(true);
    		proxyFactory.setInterfaces(UserInterface.class); 
    
            UserService proxy = (UserService) proxyFactory.getProxy();
            proxy.test();
        }
    }
    

    在上面的代码中,这里setInterfaces()设置接口,如果UserService类实现了UserInterface接口,但是没有调用该方法进行设置,那么下方源码中的if判断还是为没有实现接口,ProxyFactory不会自动判断类有没有实现接口,Spring它是自己做了相应的处理逻辑

    那么ProxyFactory在源码中是如何选择去进行JDK还是cjlib的动态代理嘞?我们通过getProxy() —> createAopProxy()

    public Object getProxy() {
        return createAopProxy().getProxy();
    }
    
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
       // inNativeImage()是不是在GraalVM虚拟机上运行
       // 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快
       // 或者isProxyTargetClass为true,
       // 或者被代理对象没有实现接口,
       if (!NativeDetector.inNativeImage() &&
             (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.");
          }
           // 如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理
          if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
             return new JdkDynamicAopProxy(config);
          }
          return new ObjenesisCglibAopProxy(config);
       }
       else {
          return new JdkDynamicAopProxy(config);
       }
    }
    

    通过上面的createAopProxy()方法我们已经知道了ProxyFactory应该使用哪一种动态代理,接下来就是调用getProxy()方法去创建代理对象了,在AopProxy接口中getProxy()方法有两个实现类

    在这里插入图片描述

    就拿JDK动态代理举例,直接调用newProxyInstance()方法创建一个代理对象返回。

    @Override
    public Object getProxy() {
       return getProxy(ClassUtils.getDefaultClassLoader());
    }
    
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
       if (logger.isTraceEnabled()) {
          logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
       }
       // this实现了InvocationHandler
       return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
    }
    



    ProxyFactory代理对象执行过程

    在线高清流程图

    在这里插入图片描述



    执行过程

    不过是通过jdk还是cjlib创建的动态代理对象,他们的执行过程其实是一样的。就拿jdk动态代理举例,在JdkDynamicAopProxy类的invoke()方法

    1. 在创建ProxyFactory代理对象之前,需要往ProxyFactory中先添加Advisor

    2. 代理对象在执行某个方法时,会把ProxyFactory中的Advisor都取出来进行与该方法进行匹配筛选

    3. 把和方法匹配的Advisor封装成MethodInterceptor

    4. 把和方法匹配的Advisor封装成MethodInterceptor链、代理对象、目标对象、目标方法、目标方法参数、目标类class封装成一个MethodInvocation对象

    5. 执行MethodInvocation对象的proceed()方法,开始执行各个MethodInterceptor以及被代理对象的目标方法

    6. 按照循序调用每个MethodInterceptor的invoke()方法,invoke()方法里面会递归调用proceed()方法,并且把MethodInvocation对象传入invoke()方法

    7. 直到调用完最后一个MethodInterceptor,就会去调用invokeJoinpoint()方法执行被代理类的目标方法



    核心思想

    核心思想就是:

    1. proceed()判断是不是最后一个MethodInterceptor,如果不是就按顺序取MethodInterceptor并调用它的的invoke()方法

    2. 各个MethodInterceptor的invoke()方法中,再去递归调用proceed()方法

      各个MethodInterceptor的invoke()方法中有自己的实现逻辑,比如MethodBeforeAdviceInterceptor,它先调用advice对应方法再去调用proceed()方法,而AfterReturningAdviceInterceptor它的invoke()方法中就是先递归调用proceed()方法,再调用advice对应方法



    执行方法匹配Advisor

    在执行过程中,重点的两个位置就是找到匹配的Advisor并封装成MethodInterceptor、递归调用proceed()方法去执行

    代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor。接下来看具体的实现,入口方法是AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice()

    一个完整的Pointcut,它其实是可以进行类匹配,还可以继续方法匹配的,还可以进行带有方法参数的匹配

    new Pointcut() {
        @Override
        public ClassFilter getClassFilter() {
            return new ClassFilter() {
                @Override
                public boolean matches(Class<?> clazz) {
                    // 这里进行类的匹配
                    return false;
                }
            };
        }
    
        @Override
        public MethodMatcher getMethodMatcher() {
            return new MethodMatcher() {
                @Override
                public boolean matches(Method method, Class<?> targetClass) {
                    // 这里进行方法的匹配
                    return false;
                }
    
                @Override
                public boolean isRuntime() {
                    // 这里返回true时,才会去进行下面带有方法参数的匹配
                    return false;
                }
    
                @Override
                public boolean matches(Method method, Class<?> targetClass, Object... args) {
                    // 带有方法参数的匹配
                    return false;
                }
            };
        }
    };
    

    源码的匹配代码如下

    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
        Advised config, Method method, @Nullable Class<?> targetClass) {
    
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        // 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor)
        // 添加的时候会控制顺序
        Advisor[] advisors = config.getAdvisors();
        List<Object> interceptorList = new ArrayList<>(advisors.length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        Boolean hasIntroductions = null;
    
        // 遍历Advisor
        for (Advisor advisor : advisors) {
            if (advisor instanceof PointcutAdvisor) {
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                // 先匹配类
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
    
                    // 再匹配方法
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    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);
                    }
    
                    // 如果匹配
                    if (match) {
    					// 将Advisor封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdvice
                        // 一般情况下 一个Advisor只会对应一个MethodInterceptor,数组中一般就只有一个
                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                        // 如果这里为true,那么就会把匹配的MethodInterceptor封装为InterceptorAndDynamicMethodMatcher类型保存
    					// 在后面执行proceed()方法时就会去进行带有方法参数的匹配
                        // 如果为false,那么就直接保存
                        if (mm.isRuntime()) {
                            for (MethodInterceptor interceptor : interceptors) {
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }
                        }
                        else {
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
    
                    // 最终,interceptorList中存储的是当前正在执行的Method所匹配的MethodInterceptor,可能动态的,也可能是非动态的,
                    // 找到Method所匹配的MethodInterceptor后,就会开始调用这些MethodInterceptor,如果是动态的,会额外进行方法参数的匹配
                }
            }
            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 {
                // 将Advisor封装成为Interceptor
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
    
        return interceptorList;
    }
    



    具体执行proceed()方法

    在执行过程中,重点的两个位置就是找到匹配的Advisor并封装成MethodInterceptor、递归调用proceed()方法去执行

    在该方法中就会从MethodInterceptor集合中取出来,并调用各自的invoke()方法,在调用过程中会把this自己传递过去,而在MethodInterceptor的invoke()方法中又会调用proceed()方法,就这样完成了循环遍历。

    public Object proceed() throws Throwable {
    
        // We start with an index of -1 and increment early.
        // currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1
        // 当调用完了最后一个interceptor后就会执行被代理方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }
    
        // currentInterceptorIndex初始值为-1,取一个MethodInterceptor出来
        Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    
        // 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
        // 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
        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 {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                // 不匹配则执行下一个MethodInterceptor,跳过当前的MethodInterceptor
                return proceed();
            }
        }
        else {
    
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            // 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
            // 比如MethodBeforeAdviceInterceptor
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }
    



    各注解对应的MethodInterceptor

    • @Before对应的是AspectJMethodBeforeAdvice,在进行动态代理时会把AspectJMethodBeforeAdvice转成MethodBeforeAdviceInterceptor
      • 先执行advice对应的方法
      • 再执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    • @After对应的是AspectJAfterAdvice,直接实现了MethodInterceptor
      • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
      • 再执行advice对应的方法
    • @Around对应的是AspectJAroundAdvice,直接实现了MethodInterceptor
      • 直接执行advice对应的方法,由@Around自己决定要不要继续往后面调用
    • @AfterThrowing对应的是AspectJAfterThrowingAdvice,直接实现了MethodInterceptor
      • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
      • 如果上面抛了Throwable,那么则会执行advice对应的方法
    • @AfterReturning对应的是AspectJAfterReturningAdvice,在进行动态代理时会把AspectJAfterReturningAdvice转成AfterReturningAdviceInterceptor
      • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
      • 执行上面的方法后得到最终的方法的返回值
      • 再执行Advice对应的方法
    try{
        Around1
        Before
        targetMethod();
        AfterReturning
        Around2
    } catch(){
        AfterThrowing
    } finaly{
       After 
    }
    






    @EnableAspectJAutoProxy

    在线高清流程图

    在这里插入图片描述



    上面的内容都是在分析ProxyFactory,也是为了更好的了解SpringAOP。接下来就来分析Spring中的实现

    我们一般都是先定义一个切面类,

    @Aspect
    @Component
    public class HushangAspect {
    
    	@Before("execution(public void com.zhouyu.service.UserService.test())")
    	public void husahngBefore(JoinPoint joinPoint){
    		System.out.println("before...");
    	}
    
        
    	@Pointcut("execution(public void com.zhouyu.service.UserService.test())")
    	public void a(){
    
    	}
    
    	@After("a()")
    	public void hushangAfter(JoinPoint joinPoint){
    		System.out.println("After...");
    	}
    
    	@AfterThrowing("a()")
    	public void hushangAfterThrowing(){
    		System.out.println("AfterThrowing...");
    	}
    
    	@Around("a()")
    	public void hushangAround(ProceedingJoinPoint joinPoint) throws Throwable {
    		System.out.println("Aroud1...");
    		joinPoint.proceed();
    		System.out.println("Aroud2...");
    	}
    }
    

    但是此时该类方法上面的注解Spring是没有去解析的,我们还需要在配置类上面加一个@EnableAspectJAutoProxy注解

    @EnableAspectJAutoProxy注解它所做的事其实就是把@EnableAspectJAutoProxy注解中设置的proxyTargetClassexposeProxy这两个参数值赋值给BeanDefinition,并且往Spring容器中添加一个AnnotationAwareAspectJAutoProxyCreator类型的bean对象,它的父类是AbstractAutoProxyCreator,它是一个BeanPostProcessor类型。在初始化后调用BeanPostProcessor时就会执行AnnotationAwareAspectJAutoProxyCreator这个类

    在这里插入图片描述

    1. 初始化后,进行AOP的入口是AbstractAutoProxyCreator.postProcessAfterInitialization(),这里会去找到当前创建的bean所有匹配的Interceptor,然后把当前bean封装成为一个TargetSource对象,一起通过ProxyFactory去创建一个代理对象。

    2. 对找到的Advisor与当前创建的bean进行匹配筛选的是AbstractAdvisorAutoProxyCreator.findEligibleAdvisors()方法

    3. 去找所有的Advisor就是AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors()方法了,它会去找所有的@Aspect注解修饰的类,会去解析所有的切点表达式与相应的方法,进而生成一个Advisor集合



    补充知识点

    如果目标方法有参数,

    @Component
    public class UserService {
    
       public void test(String a, String b){
          System.out.println("test()...");
       }
    
    }
    

    我在切面的方法增强中想要获取

    @Before(value = "execution(public void com.zhouyu.service.UserService.test(..)) && args(a,b)", argNames = "a,b")
    public void husahngBefore(String a, String b){
       System.out.println(a);
       System.out.println(b);
       System.out.println("before...");
    }
    
  • 相关阅读:
    面试题:JS如何最快的执行垃圾回收机制
    LeetCode841. Keys and Rooms
    修改history记录、定时校正服务器时间、停止IPv6网络服务、调整最大文件打开数、关闭写磁盘I/O功能、配置SSH服务
    数据库存储引擎和数据类型详细介绍
    Http协议之Content-Type理解
    猿创征文|实战开发openGauss DataStudio的sql联想结构
    SQL Server数据库理论篇(进行时......)
    关于ORVIBO的HomeAI V4.0的分析
    Zabbix小实验
    2022DAMA数据治理最佳培训机构奖
  • 原文地址:https://blog.csdn.net/qq_44027353/article/details/139998488