侧边栏壁纸
博主头像
Leokoの小破站博主等级

行动起来,活在当下

  • 累计撰写 14 篇文章
  • 累计创建 10 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Spring AOP 详解

Leoko
2023-04-10 / 0 评论 / 0 点赞 / 66 阅读 / 65918 字

了解 Spring AOP 前必须知道动态代理,这是基础。

原生JDK 动态代理与 CGLIB 动态代理

1. JDK 动态代理

JDK 动态代理是基于接口的,代理的类必须实现某个接口

public interface UserService {
    void addUser();
}
​
public class UserServiceImpl implements UserService {
    public void addUser() {
        // 1
        System.out.println("addUser 方法执行了");
    } 
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
​
public class Main {
    
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        // 生成代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 2
                        System.out.println("代理方法执行了");
                        // 3
                        return method.invoke(target, args);
                    }
                });
        // 4
        proxy.addUser();
    }
}

启动后,执行代理对象的 addUser() 方法,控制台会先输出代理对象的 2 处的语句,然后再输出 1处的语句。

将断点打在 4 处,可查看生成的代理对象:

image-20230912194648317

$Proxy:代理对象所属的类。

h:就是 InvocationHandler

target:被代理对象,InvocationHandler 中的 invoke 方法对原有方法增强后需要执行被代理对象的原始方法,即 3 处。

想查看生成的代理类,需要 main 方法中加入 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true"); 便能看到生成的类。

image-20230912195318707

可以看到 $Proxy0 实现了 UserService 接口,所以说 JDK 动态代理是基于接口的,代理对象执行 addUser的时候,实际执行的是 h 也是就 InvocationHandlerinvoke 方法。

2. CGLIB 代理

CGLIB 代理是基于类的,会创建被代理对象的子类,所以使用 CGLIB 有几个点需要注意:

  • 被代理的类不能是 final 的,因为 final 类型的 Class 无法继承。

  • 被代理的类必须有默认的或者无参构造方法,因为底层反射创建代理对象的时获取不到构造方法参数

使用 CGLIB 需要依赖对应 jar 包:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.1</version>
</dependency>

修改 main 方法:

public static void main(String[] args) {
      // 查看 cglib 生成的代理对象
       System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "cglib");
      UserServiceImpl target = new UserServiceImpl();
      // 生成代理对象
      UserServiceImpl proxy = (UserServiceImpl) Enhancer.create(target.getClass(), new MethodInterceptor() {
          @Override
          public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
              System.out.println("代理方法执行了");
              return method.invoke(target, args);
          }
      });
      proxy.addUser();
}

第一行的代码是在当前项目下的 cglib 目录下生成对应的代理类。main 方法执行效果和 JDK 动态代理的效果一样。进入 cglib 目录查看代理类:

可以看到生成的代理对象继承了 UserServiceImpl,里面的 addUser 方法也和 JDK 动态代理差不多,可自行试验查看。

Spring AOP 中的代理

Spring AOP 生成的代理和原生的 JDK 代理、 CGLIB 稍微有点不一样,先写一个简单的 AspectJ 切面,Spring 版本为 5.3.19

image-20230913153510042

@Configuration
@ComponentScan("com.main")
@EnableAspectJAutoProxy        // 开启注解 AOP
public class MainConfiguration {
}
​
@Aspect
@Component
public class UserAspect {
​
    @Before("execution(public * com.main.UserService.*(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("代理方法执行了");
    }
}
​
public class Main {
​
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfiguration.class);
        UserService bean = context.getBean(UserService.class);
        bean.addUser();
    }
​
}

@EnableAspectJAutoProxy 注解中,有一个属性 proxyTargetClass,这个就是控制 Spring AOP 使用的是 JDK 动态代理还是 CGLIB 动态代理,默认值为 false,代表使用 JDK 动态代理。

但是这并不代表设置为 false 就全部使用 JDK 动态代理,因为 JDK 动态代理是基于接口的,如果一个类没有实现接口,那就无法使用 JDK 动态代理,需要使用 CGLIB 代理,这点需要注意。

1. JDK动态代理

同样在 main 方法第一行加入 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true"); 查看生成类。

image-20230913160257304

可以看相比于原生的 JDK 动态代理,Spring AOP 生成的代理类多实现了 SpringProxyAdvisedDecoratingProxy 三个接口,对着三个接口有印象就行,后续源码中会涉及到。

2. CGLIB 代理

MainConfiguration 手动将 @EnableAspectJAutoProxy 注解的 proxyTargetClass 属性设置为 true,这样所有的代理类都是使用 CGLIB 代理生成。同样在 main 方法第一行加上 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "cglib");

image-20230913161208754

相比原生的 CGLIB 代理,Spring AOP 生成的代理类多实现了 SpringProxyAdvised 接口。

注意:这里的 Factory 接口是org.springframework.cglib.proxy包下的,而原生的 CGLIB 代理类 Factory 接口是 net.sf.cglib.proxy 包下的。

Sping AOP 源码分析

1. @EnableAspectJAutoProxy 注解

点进 @EnableAspectAutoProxy 注解

image-20230914092027135

可以看到内部 Import 了一个类:AspectJAutoProxyRegistrar,而这个类实现了 ImportBeanDefinitionRegistrar 接口,如果熟悉 Spring IOC 的话,那应该对这个接口很熟悉,如果不知道的话,建议先去看看 Spring IOC 的原理,因为后面的讲解是基于 IOC 来的。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
​
    /**
     * Register, escalate, and configure the AspectJ auto proxy creator based on the value
     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
     * {@code @Configuration} class.
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 1. 注册后置处理器
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        // 2. 解析 @EnableAspectJAutoProxy 的属性并配置
        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
​
}

由于实现了 ImportBeanDefinitionRegistrar 接口,IOC 注册 beanDefinition 的时候会执行 registerBeanDefinitions() 方法,具体源码在 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions() ,不记得的可以再回顾一下。

第一行就是注册后置处理器,即代理类的创建类,而方法里面明确了要注册的 bean 的类型是 AnnotationAwareAspectJAutoProxyCreator

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
        return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
    }
​
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {
        // 指定类型:AnnotationAwareAspectJAutoProxyCreator
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

然后,根据类型构造 beanDefinition,并注册进 BeanDefinitionRegistry

private static BeanDefinition registerOrEscalateApcAsRequired(
            Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
​
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
​
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            return null;
        }
​
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }

这个注意一下 bean 的名称是变量 AUTO_PROXY_CREATOR_BEAN_NAME,实际值为 org.springframework.aop.config.internalAutoProxyCreator

2. AnnotationAwareAspectJAutoProxyCreator

通过 IDEA 查看类关系结构:

image-20230917213211082

它实现了几个重要的接口:

  • BeanPostProcessor:在 postProcessAfterInitialization 方法中创建代理对象。

  • InstantiationAwareBeanPostProcessor:拦截 bean 的创建。

  • AopInfrastructureBean:实现了该接口的 bean 不会被代理。

并继承自核心类 AbstractAutoProxyCreator

3. 初始化 AnnotationAwareAspectJAutoProxyCreator

第一步已将对应的 BeanDefinition 注册到 BeanDefinitionRegistry 中了,接下来就要初始化对应的 Bean了。而 Spring 中初始化 BeanPostProcessor 即后置处理器的地方在 AbstractApplication 中:

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            ......
            try {
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                this.invokeBeanFactoryPostProcessors(beanFactory);
                // 这里注册 BeanPostProcessor
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                ........
        }
    }

更深入的源码可以去看 IOC 那部分的文章(TODO),这里不再重复。

4. 作用时机

上一步 registerBeanPostProcessors 方法中已将把 AnnotationAwareAspectJAutoProxyCreator 初始化好了,那接下来的 bean 的创建就会被它所干预。

bean 的创建流程在 IOC 处详细说过,依次是 getBeandoGetBeancreateBeandoCreateBean。在 doCreateBean 中会真正的创建对象、属性赋值、依赖注入和初始化流程。

它对 bean 进行前置或后置处理的的主要就两个方法:postProcessBeforeInstantiationpostProcessAfterInitialization。前一个是 bean 的实例化之前拦截,后一个是 bean 初始化后拦截。

你可能会问其他的 postXXX 方法为什么没有解释一下呢,这是因为 AnnotationAwareAspectJAutoProxyCreator 只改造了 postProcessBeforeInstantiation 方法和 postProcessAfterInitialization,其他的 postXXX方法用是默认的。

image-20230919112627248

5. AnnotationAwareAspectJAutoProxyCreator # postProcessBeforeInstantiation

前面说过 AnnotationAwareAspectJAutoProxyCreator 实现了 InstantiationAwareBeanPostProcessor 接口,会拦截 bean 的实例化,具体代码在 AbstractAutowireCapableBeanFactorycreateBean 方法。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        ........
        Object beanInstance;
        try {
            // 此处拦截
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            if (beanInstance != null) {
                return beanInstance;
            }
        ........
    }
    
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = this.determineTargetType(beanName, mbd);
                if (targetType != null) {
                    // 获取所有的 InstantiationAwareBeanPostProcessor,遍历执行 postProcessBeforeInstantiation,只要有一个不返回 null,跳出遍历直接返回
                    bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }

            mbd.beforeInstantiationResolved = bean != null;
        }

        return bean;
    }    

AnnotationAwareAspectJAutoProxyCreatorpostProcessBeforeInstantiation 方法在它的父类 AbstractAutoProxyCreator 中。

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);
    // 决定是否要提前增强当前 bean
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        // 被增强过的 bean 不会再次增强
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // 基础类型的bean不会被提前增强、被跳过的bean不会被提前增强
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // 原型bean的额外处理:TargetSource
    // 此处的设计与自定义TargetSource相关,单实例bean必定返回null
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    return null;
}

5.1 InfrastructureClass

protected boolean isInfrastructureClass(Class<?> beanClass) {
    boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
        Pointcut.class.isAssignableFrom(beanClass) ||
            Advisor.class.isAssignableFrom(beanClass) ||
                AopInfrastructureBean.class.isAssignableFrom(beanClass);
    if (retVal && logger.isTraceEnabled()) {
        logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
    }
    return retVal;
}

可以看到 InfrastructureClass 指的是切面、切入点、增强器等等的对象,这些是参与 AOP 代理的,不应该被 AOP 代理。

5.2 shouldSkip

//注意这个方法是在 AspectJAwareAdvisorAutoProxyCreator 中的
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 获取增强器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        // 判断当前bean的名称是否与增强器的名称一致,则认为跳过
        if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
            return true;
        }
    }
    // 这里才是 AbstractAutoProxyCreator 中的
    return super.shouldSkip(beanClass, beanName);
}

// AbstractAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    //  检查beanName代表的是不是原始对象(以.ORIGINAL结尾)
	return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}

5.3 findCandidateAdvisors

获取候选的增强器,底层就是解析切面类,构造 Advisor 增强器的过程。

增强器 Advisor,在 AspectJ 中,对应切面注解 @Before 等和注解标注的方法就可以看做是一个 Advisor

// AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    List<Advisor> advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

进入父类 AbstractAdvisorAutoProxyCreator

protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    return this.advisorRetrievalHelper.findAdvisorBeans();
}
5.3.1 findAdvisorBeans 查找实现了 Advisor 接口的 bean

advisorRetrievalHelper.findAdvisorBeans() 这段源码拆开来看:

public List<Advisor> findAdvisorBeans() {
    String[] 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!
        // 这里没有初始化对应的 bean
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }
}

上面代码就是将 Advisor 的实现类找出来,如果没有,直接返回,不执行下面的逻辑。

List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
    if (isEligibleBean(name)) {
        if (this.beanFactory.isCurrentlyInCreation(name)) {
            // logger ......
        }
        else {
            try {
                advisors.add(this.beanFactory.getBean(name, Advisor.class));
            } // catch ......
        }
    }
}
return advisors;
}

只关注重点 beanFactory.getBean,这个应该很熟悉了,包含了 bean 的初始化,通过 debug 可以发现,没有候选的增强器。

image-20230918194544378

5.3.2 aspectJAdvisorsBuilder.buildAspectJAdvisors

就是将 AspectJ 切面类,转成增强器。

5.3.2.1 逐个解析IOC容器中所有的bean类型
// BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;

    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }
                    Class<?> beanType = this.beanFactory.getType(beanName, false);

这里将容器中所有的 bean 都取出来(父类型为 Object),在不初始化对应 bean 的前提下,拿到 beanName 对应的 beanclass

5.3.2.2 解析 Aspect 切面类,构造增强器
......
if (this.advisorFactory.isAspect(beanType)) {
    // 当前的 bean 是一个切面类
    aspectNames.add(beanName);
    AspectMetadata amd = new AspectMetadata(beanType, beanName);
    if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
        // 单实例 bean
        MetadataAwareAspectInstanceFactory factory =
            new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
        List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
        if (this.beanFactory.isSingleton(beanName)) {
            this.advisorsCache.put(beanName, classAdvisors);
        }
        else {
            this.aspectFactoryCache.put(beanName, factory);
        }
        advisors.addAll(classAdvisors);
    }
    else {
        // Per target or per this.
        if (this.beanFactory.isSingleton(beanName)) {
            throw new IllegalArgumentException("Bean with name '" + beanName +
                                               "' is a singleton, but aspect instantiation model is not singleton");
        }
        MetadataAwareAspectInstanceFactory factory =
            new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
        this.aspectFactoryCache.put(beanName, factory);
        advisors.addAll(this.advisorFactory.getAdvisors(factory));
    }
}
// AbstractAspectJAdvisorFactory
public boolean isAspect(Class<?> clazz) {
    return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

private boolean hasAspectAnnotation(Class<?> clazz) {
    return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

advisorFactory.getAdvisors,构造增强器:

// ReflectiveAspectJAdvisorFactory
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
        // 切面类对应的 class
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        // 再次校验类上是否有 @Aspect 注解
		validate(aspectClass);

		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
        // 解析通知方法,封装为 advisor
		for (Method method : getAdvisorMethods(aspectClass)) {
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}
private static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS
			.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    List<Method> methods = new ArrayList<>();
    ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
    if (methods.size() > 1) {
        methods.sort(adviceMethodComparator);
    }
    return methods;
}

上面这个方法就是把切面类中没有标注 @Pointcut 注解的方法取出来,并根据相关规则排序。

改造一下之前的 UserAspect,然后在 getAdvisorMethods 处打断点查看取出的方法:

@Aspect
@Component
public class UserAspect {

    @Before("execution(public * com.main.UserService.*(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("代理方法执行前");
    }

    @After("execution(public * com.main.UserService.*(..))")
    public void after(JoinPoint joinPoint) {
        System.out.println("代理方法执行后");
    }
    
    public void noAdvice() {
        System.out.println("非通知方法");
    }
}

image-20230919104108318

可以看到将 UserAspect 中所有的方法取出来了,即便方法上没有 @Before 等通知注解。既然方法上没有通知注解,为什么还取出来呢,别急,下面的方法其实会再做一次过滤。

// ReflectiveAspectJAdvisorFactory
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {
   
    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
   
    AspectJExpressionPointcut expressionPointcut = getPointcut(
        candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }
    // 增强器的创建
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                                                          this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    // 检查方法上面的通知注解
    AspectJAnnotation<?> aspectJAnnotation =
        AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }
    // 根据注解的类型, 构造切入点表达式 
    AspectJExpressionPointcut ajexp =
        new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    if (this.beanFactory != null) {
        ajexp.setBeanFactory(this.beanFactory);
    }
    return ajexp;
}

// AbstractAspectJAdvisorFactory
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
			Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};

protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
    for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
        AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
        if (foundAnnotation != null) {
            return foundAnnotation;
        }
    }
    return null;
}

ASPECTJ_ANNOTATION_CLASSES 包含了所有通知注解,没有注解的方法会被过滤。如果有,则将切入点表达式的内容,以及参数等信息,封装到 AspectJExpressionPointcut 中。

再打断点,最终可以发现没有标注通知注解的方法已经被过滤掉了:

image-20230919110639903

另外对于多实例 bean 的处理,核心依旧是 advisorFactory.getAdvisors,只是没有用到 advisorsCache 这个缓存区,这也说明多实例 bean 的解析是多次执行的。

else {
    // Per target or per this.
    if (this.beanFactory.isSingleton(beanName)) {
        throw new IllegalArgumentException("Bean with name '" + beanName +
                                           "' is a singleton, but aspect instantiation model is not singleton");
    }
    MetadataAwareAspectInstanceFactory factory =
        new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
    this.aspectFactoryCache.put(beanName, factory);
    advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
5.3.2.3 增强器的创建

getAdvisor 最后会创建一个增强器对象并返回。

return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);

可以看构造方法中的参数:

  • expressionPointcut:AspectJ 切入点表达式的封装。

  • candidateAdviceMethod:标有通知注解的方法。

  • this:当前的 ReflectiveAspectJAdvisorFactory

  • aspectInstanceFactory:前面代码中的 MetadataAwareAspectInstanceFactory 对象。

可以看到增强器本身的结构就是一个切入点表达式 + 一个通知方法,和之前说的完全一致。

5.3.2.4 增强器汇总

buildAspectJAdvisors() 方法最后几行:

if (aspectNames.isEmpty()) {
    return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
    List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
    if (cachedAdvisors != null) {
        advisors.addAll(cachedAdvisors);
    }
    else {
        MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
        advisors.addAll(this.advisorFactory.getAdvisors(factory));
    }
}
return advisors;

增强器汇总完毕,并且将这些数据都放到缓存里面了,接下来就是和 bean 的匹配了。

6. AnnotationAwareAspectJAutoProxyCreator # postProcessAfterInitialization

阅读过 IOC 的应该知道,最终 bean 的初始化会被 BeanPostProcessorpostProcessAfterInitialization 处理,进入到 AnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInitialization 方法中,这个方法其实在父类 AbstractAutoProxyCreator 中,最后会调用 wrapIfNecessary 方法。

// AbstractAutoProxyCreator
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            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;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

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

先看前面一部分,这块代码和前面的 postProcessBeforeInstantiation 很像,这里不再赘述。

image-20230922104149273

6.2 getAdvicesAndAdvisorsForBean

这个方法很明显就是根据当前正在初始化的 bean 去匹配增强器。

// AbstractAdvisorAutoProxyCreator
protected Object[] getAdvicesAndAdvisorsForBean(
    Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    // 核心处理
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        // DO_NOT_PROXY 这个静态变量就是 null
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
6.2.1 findCandidateAdvisors

这个方法在 5.3 章节的分析过了,忘记了的话可以跳回去看。

// AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    // 找 Spring 的原生的增强器
    List<Advisor> advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    if (this.aspectJAdvisorsBuilder != null) {
        // 找 AspectJ 封装的增强器
        // buildAspectJAdvisors 方法 5.3.2 章节中已经分析过了, 这里可以直接从缓存中拿数据
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}
6.2.2 findAdvisorsThatCanApply

获取到所有的增强器之后,进行匹配。

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

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        // 交给 AopUtils
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

// AopUtils
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new ArrayList<>();
    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 整体逻辑分为两个部分,前面是针对引介通知的增强器作筛选,后面是普通的方法通知封装的增强器。

对于引介增强器的匹配就不研究了,用得少,感兴趣的可以自行研究。主要还是看普通的增强器。

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    if (advisor instanceof IntroductionAdvisor) {
        // 引介增强器
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    else if (advisor instanceof PointcutAdvisor) {
        // 普通切入点增强器
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        // It doesn't have a pointcut so we assume it applies.
        return true;
    }
}

对不同的增强器会有不同的处理逻辑,主要看切入点增强器的处理:

// AopUtils
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    Assert.notNull(pc, "Pointcut must not be null");
    // 连类都切入不进去,那干脆没必要往下走了
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;	
    }

    MethodMatcher methodMatcher = pc.getMethodMatcher();
    if (methodMatcher == MethodMatcher.TRUE) {
        return true;
    }

    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }

    Set<Class<?>> classes = new LinkedHashSet<>();
    if (!Proxy.isProxyClass(targetClass)) {
        classes.add(ClassUtils.getUserClass(targetClass));
    }
    // 将类实现的接口也加入进来
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(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;
}

怎么匹配的后面再分析。

回到 findEligibleAdvisors 方法,打断点查看 userService 匹配到的增强器。

image-20230922142607608

6.2.3 extendAdvisors

根据名字理解这个方法扩展了增强器,在这个方法后面打断点,发现还真的多了一个增强器。

image-20230922143028064

// AspectJAwareAdvisorAutoProxyCreator
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}

// AspectJProxyUtils
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
    if (!advisors.isEmpty()) {
        boolean foundAspectJAdvice = false;
        for (Advisor advisor : advisors) {
            if (isAspectJAdvice(advisor)) {
                foundAspectJAdvice = true;
                break;
            }
        }
        // 如果有 AspectJ 包装的增强器且当前的 advisors 里面没有ExposeInvocationInterceptor           // 就在 advisors 最前面加一个 ExposeInvocationInterceptor.ADVISOR
        if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
            advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
            return true;
        }
    }
    return false;
}

ExposeInvocationInterceptor.ADVISOR 是什么呢?点进去:

public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();

public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
    @Override
    public String toString() {
        // 这里重写的 toString 方法
        return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
    }
};

public DefaultPointcutAdvisor(Advice advice) {
    this(Pointcut.TRUE, advice);
}

那已经很清楚了,就是一个增强器,类型是 DefaultPointcutAdvisor,增强器的通知(Advice)是 ExposeInvocationInterceptor

那这个 ExposeInvocationInterceptor 有什么用呢?

public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
    
    private static final ThreadLocal<MethodInvocation> invocation =
			new NamedThreadLocal<>("Current AOP method invocation");
    .....
    
    @Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		MethodInvocation oldInvocation = invocation.get();
		invocation.set(mi);
		try {
			return mi.proceed();
		}
		finally {
			invocation.set(oldInvocation);
		}
	}
    ...
}

上面说了这个类是一个 Advice,可以看到实现了 MethodInterceptor 接口,可以拦截 bean 方法的执行。它的 invoke 方法在当前线程的 ThreadLocal 中放入了当前正在执行的代理对象的方法执行包装。并且这个增强器总是在增强器链中第一个执行,所以上面代码含义就是让后面的增强器都拿到当前正在执行的 MethodInvocation

6.3 createProxy 创建代理对象

回到 wrapIfNecessary 方法:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // getAdvicesAndAdvisorsForBean 找不到匹配的增强器会返回 DO_NOT_PROXY(null)
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理对象
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }   
}

匹配到了 bean 对应的增强器后,接下来就是创建代理对象了。

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
    // 记录被代理 bean 的原始类型
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }
	// 初始化代理工厂
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);
	// 这里即 @EnableAspectJAutoProxy 注解中 proxyTargetClass 的值 
    if (proxyFactory.isProxyTargetClass()) {
        // cglib 代理
        if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
            for (Class<?> ifc : beanClass.getInterfaces()) {
                proxyFactory.addInterface(ifc);
            }
        }
    }
    else {
        // JDK 动态代理
        if (shouldProxyTargetClass(beanClass, beanName)) {
            // 设置 cglib 代理
            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);
    }

    // Use original ClassLoader if bean class not locally loaded in overriding class loader
    ClassLoader classLoader = getProxyClassLoader();
    if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
        classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
    }
    return proxyFactory.getProxy(classLoader);
}
6.3.1 shouldProxyTargetClass

先分析下 shouldProxyTargetClass 方法,在 proxyTargetClassfalse 的情况下:

protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
    return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
            AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
}

// AutoProxyUtils
public static boolean shouldProxyTargetClass(
    ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {

    if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
        BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
        return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
    }
    return false;
}

可以看到主要是判断被代理的 beanbeanDefinition 中对应属性为 PRESERVE_TARGET_CLASS_ATTRIBUTE 的值是否为 true。既然这里是 getAttribute,那肯定有地方 setAttribute。将源码下下来,CTRL + 鼠标左键找到 setAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE,值) 的地方。可以发现是在 ConfigurationClassPostProcessor 这个类 enhanceConfigurationClasses 方法中 set 的,看过前面 IOC 的文章的小伙伴应该有印象吧,这个类可是很重要的。

enhanceConfigurationClasses 是哪里被调用的?还是在这个类里面:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    .........
    // 这里调用
    enhanceConfigurationClasses(beanFactory);
    beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

可以看到是在 postProcessBeanFactory 方法中调用的,postProcessBeanFactory 又是 IOC 部分讲过的,所以说看 AOP 之前要先熟悉一下 IOC 哦,不然看到一半就懵了。

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    .......
    Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
        Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
        ........
        if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
            .........
            // 往 configBeanDefs 里 put 数据
            configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
        }
    }
    if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
        // nothing to enhance -> return immediately
        enhanceConfigClasses.end();
        return;
    }

    ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
    for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
        AbstractBeanDefinition beanDef = entry.getValue();
        // If a @Configuration class gets proxied, always proxy the target class
        // 这里 set 了属性名 PRESERVE_TARGET_CLASS_ATTRIBUTE 的值为 true
        beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
        ..........
}

省略了部分代码,最后一行对 beanDefinitionPRESERVE_TARGET_CLASS_ATTRIBUTE 属性赋值了,但是前提是只有在 configBeanDefs 中的 beanDefinition 才会被赋值。那 configBeanDefs 什么时候才不为空呢?往上找往 configBeanDefsput 数据的代码,发现只有 beanDefinition 中属性为 ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE 对应的值为 ConfigurationClassUtils.CONFIGURATION_CLASS_FULL 时这个 beanDefinition 才会加入到 configBeanDefs 中。

还是老方法,CTRL + 鼠标左键找到 ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTEsetAttribute 中的地方,发现在 ConfigurationClassUtilscheckConfigurationClassCandidate 方法(看到 ConfigurationClassUtils 是不是很熟悉,还是 IOC 那部分讲过的),继续往上找调用此方法的地方,最终还是回到了类 ConfigurationClassPostProcessor ,在 processConfigBeanDefinitions 方法中,继续往上找,postProcessBeanDefinitionRegistry 方法,这个方法又是 IOC 那部分讲过的。

整个调用链就清晰了 ConfigurationClassPostProcessor # postProcessBeanDefinitionRegistry

-> ConfigurationClassPostProcessor # processConfigBeanDefinitions -> ConfigurationClassUtils.checkConfigurationClassCandidate

public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    ......
    // 被 @Configuration 注解标注的类,即注解配置类才会设置属性
    Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    else if (config != null || isConfigurationCandidate(metadata)) {
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {
        return false;
    }
    ......
}

分析到这就很清楚了,只有被 @Configuration 标注的类才会设置 CONFIGURATION_CLASS_ATTRIBUTEtrue,所以 AopUtils # shouldProxyTargetClass 针对的是需要被代理注解配置类。可以做个小实验,修改一下 MainConfigurationUserAspectafter 方法,让 UserAspect 可以拦截到 MainConfiguration,并在 createProxy 处打断点查看结果:

@Configuration
@ComponentScan("com.main")
@EnableAspectJAutoProxy(proxyTargetClass = false)
public class MainConfiguration {

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

@Aspect
@Component
public class UserAspect {

    @Before("execution(public * com.main.UserServiceImpl.*(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("代理方法执行前");
    }

    @After("execution(public * com.main.MainConfiguration.*(..))")
    public void after(JoinPoint joinPoint) {
        System.out.println("代理方法执行后");
    }

    public void noAdvice() {
        System.out.println("非通知方法");
    }
}

image-20230923152915085

进到 if 的方法体里面了,说明 shouldProxyTargetClass 是返回的 true,而 userService 只是普通 bean,进入到 else 方法体里面了。

image-20230923153033674

6.3.2 evaluateProxyInterfaces

非配置类进到这个方法,在 proxyTargetClassfalse 的情况下:

// ProxyProcessorSupport
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
    // 获取类实现的接口
    Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
    boolean hasReasonableProxyInterface = false;
    for (Class<?> ifc : targetInterfaces) {
        // 检查实现的接口是否可代理
        if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
            ifc.getMethods().length > 0) {
            hasReasonableProxyInterface = true;
            break;
        }
    }
    if (hasReasonableProxyInterface) {
        for (Class<?> ifc : targetInterfaces) {
            proxyFactory.addInterface(ifc);
        }
    }
    else {
        // 没有实现接口, 将 proxyTargetClass 设置为 true, 表示需要 cglib 代理
        proxyFactory.setProxyTargetClass(true);
    }
}
6.3.3 buildAdvisors
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
    // 这个地方是适配Spring原生AOP的MethodInterceptor,感兴趣的小伙伴可自行研究
    Advisor[] commonInterceptors = resolveInterceptorNames();

    List<Object> allInterceptors = new ArrayList<>();
    if (specificInterceptors != null) {
        if (specificInterceptors.length > 0) {
            allInterceptors.addAll(Arrays.asList(specificInterceptors));
        }
        // 组合原生的方法拦截器,共同作为AOP的通知织入
        if (commonInterceptors.length > 0) {
            if (this.applyCommonInterceptorsFirst) {
                allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
            }
            else {
                allInterceptors.addAll(Arrays.asList(commonInterceptors));
            }
        }
    }
    .........
    Advisor[] advisors = new Advisor[allInterceptors.size()];
    for (int i = 0; i < allInterceptors.size(); i++) {
        advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
    }
    return advisors;
}

最下面有一个 dvisorAdapterRegistry.wrap 方法,字面意思是包装,点进去看:

// DefaultAdvisorAdapterRegistry
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    if (adviceObject instanceof Advisor) {
        return (Advisor) adviceObject;
    }
    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);
}

很简单了,就是将可以支持转换 / 包装为 Advisor 类型的对象适配成 Advisor。适配的类型,内置的只有 MethodInterceptor 和几种原生的 Advice

6.3.4 proxyFactory.getProxy

接下来就是真正创建代理对象了:

// ProxyFactory
public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}
6.3.4.1 createAopProxy
// ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}

private void activate() {
    this.active = true;
    for (AdvisedSupportListener listener : this.listeners) {
        listener.activated(this);
    }
}

这里有一个监听器通知的动作,而 AdvisedSupportListener 只在 ProxyCreatorSupport 中使用,查看 Spring 也没有对应的实现接口,我们开发的话基本也不使用,所以稍微看一下就行,主要还是看 getAopProxyFactory().createAopProxy(this)

// ProxyCreatorSupport
public AopProxyFactory getAopProxyFactory() {
    return this.aopProxyFactory;
}

可以通过 debug 发现 aopProxyFactory 的类型是 DefaultAopProxyFactory

image-20230924150531673

进入到它的 createAopProxy 方法中:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    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) || ClassUtils.isLambdaClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        // 否则使用 cglib 代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

看到熟悉的 JDKCGLIB 动态代理的字眼了,选择哪种方式就是在这里决定的。

6.3.4.2 AopProxy # getProxy

创建完 AopProxy 后,开始创建代理对象,以 JdkDynamicAopProxy 为例:

public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }
    // jdk动态代理的API
    return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

最下面就是 JDKProxy.newProxyInstance

0

评论区