> For the complete documentation index, see [llms.txt](https://ldbmcs.gitbook.io/java/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ldbmcs.gitbook.io/java/java-frameworks-38/spring/spring-aop/spring-aop-zhong-de-bean-shi-ru-he-bei-aop-dai-li-de.md).

# Spring AOP中的Bean是如何被AOP代理的

前面咱已经知道，最终 bean 的初始化会被 `BeanPostProcessor` 的 `postProcessAfterInitialization` 处理，进入到 `AnnotationAwareAspectJAutoProxyCreator` 的 `postProcessAfterInitialization` 方法中，它又要调用 `wrapIfNecessary` 方法来尝试创建代理，咱深入方法内部来研究。

## 1. wrapIfNecessary

```java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 判断决定是否是不会被增强的 bean
    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);
        // 创建代理对象的动作
        // 注意此处它创建了一个SingletonTargetSource，将bean包装起来了
        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;
}
```

这里前面的筛选过滤懂还是蛮简单的，咱就不关注了，重点是关注一下中间的获取增强器，以及下面的创建代理对象，两个动作。

### 1.1 getAdvicesAndAdvisorsForBean

这个方法很明显是根据当前正在初始化的 bean ，去匹配获取能切入的增强器，它的源码看上去不复杂：

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

毫无疑问，核心逻辑是 `findEligibleAdvisors` 方法咯，继续往里走：

```java
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取所有增强器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 筛选出可以切入当前bean的增强器
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 添加额外的增强器
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        // 增强器排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}
```

这个方法就很复杂了，尽管只有几行，但都是封装好的方法，咱一个一个的展开来看。

#### 1.1.1 findCandidateAdvisors

又回到 `AnnotationAwareAspectJAutoProxyCreator` 了：

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

可以发现，这个方法只是把 SpringFramework 原生的 AOP 增强器，以及 AspectJ 形式封装的增强器都拿出来，仅此而已。

#### 1.1.2 findAdvisorsThatCanApply

所有的增强器获取到之后，下面要去匹配可以切入到当前 bean 的增强器了，咱进入到 `findAdvisorsThatCanApply` 方法中：

```java
protected List<Advisor> findAdvisorsThatCanApply(
        List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    } finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}
```

这个方法又交给 `AopUtils` 执行了，咱继续往里看：

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

可以发现，整体逻辑分为两个部分，前面是针对引介通知的增强器作筛选，后面是普通的方法通知封装的增强器。

上面的引介增强器的匹配咱就不多研究了，本来平时就用得少，咱主要还是来看对于方法的增强器，它是如何去做匹配的。进入到下面的 `canApply` 方法中：

```java
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.
        // SpringFramework也不知道咋搞了，于是就直接让它可以匹配
        return true;
    }
}
```

从这个逻辑中就可以看出，底层针对不同种的增强器，分别会有不同的判断逻辑。对于方法增强器的判断，它又调用了下面的重载方法：

```java
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) {
        // 逐个判断每个方法是否能被当前切入点表达式切入，切入则立即返回true
        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;
}
```

整体思路还是很清晰的吧，我们要理解的核心部分，是下面的这个双重循环，以此就能判断出来切入点表达式是否能对当前 bean 进行增强了。

Debug 下来，最终发现可以给 `OrderService` 匹配到的增强器一共有 2 个：（ `FinanceService` 就不看了，因为咱一开始学习的时候，就是拿它举的例子，所有的通知方法都切入它了）

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671542331402-969cb423-c1d9-4b17-9a7c-eb3c97850516.png)

#### 1.1.3 extendAdvisors

这个方法看上去蛮不起眼的，不过小伙伴们有自己 Debug 的话，过了这个方法会发现 `eligibleAdvisors` 集合中多了一个增强器：

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671542355234-0d64f4ad-77af-4e89-9fb1-bafcf242c8c2.png)

诶？它自己还有偷偷添加增强器啊，那咱看看它干了些啥：

**1.1.3.1 extendAdvisors方法的小动作**

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

// AspectJProxyUtils
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
    // Don't add advisors to an empty list; may indicate that proxying is just not required
    if (!advisors.isEmpty()) {
        boolean foundAspectJAdvice = false;
        for (Advisor advisor : advisors) {
            // Be careful not to get the Advice without a guard, as this might eagerly
            // instantiate a non-singleton AspectJ aspect...
            if (isAspectJAdvice(advisor)) {
                foundAspectJAdvice = true;
                break;
            }
        }
        // 发现有AspectJ包装的增强器，则添加一个ExposeInvocationInterceptor
        if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
            advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
            return true;
        }
    }
    return false;
}
```

逻辑不算复杂，它这个方法的关键是，判断当前可用的增强器中有没有 AspectJ 类型的，如果有的话，那就在整个增强器的列表的最前面，添加一个 `ExposeInvocationInterceptor.ADVISOR` 。

**1.1.3.2 ADVISOR是个啥？**

那这个 `ADVISOR` 又是个啥子？咱继续往里走：

```java
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();

public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
    @Override
    public String toString() {
        return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
    }
};
```

哦？合着它是个对所有 bean 都生效的增强器呗？传入的这个 `INSTANCE` 很明显是单例的设计，那到头来核心还是这个 `ExposeInvocationInterceptor` 本身。

**1.1.3.3 ExposeInvocationInterceptor又是个啥？**

那新的问题就来了：`ExposeInvocationInterceptor` 这玩意的作用是什么呢？

翻开源码的核心 invoke 方法，发现它在向当前线程的 `ThreadLocal` 中放入了当前正在执行的代理对象的方法执行包装：

```java
private static final ThreadLocal<MethodInvocation> invocation =
			new NamedThreadLocal<>("Current AOP method invocation");

public Object invoke(MethodInvocation mi) throws Throwable {
    MethodInvocation oldInvocation = invocation.get();
    invocation.set(mi);
    try {
        return mi.proceed();
    }
    finally {
        invocation.set(oldInvocation);
    }
}
```

每次都在增强器链的第一个执行，并且放入 `ThreadLocal` 变量中，那这意图就很明显了：它可以让后面的增强器都拿到当前正在执行的 `MethodInvocation` 。至于哪里会用到 `MethodInvocation` ，咱目前还没有遇到，后面如果遇到了咱再留意。

或许会有小伙伴产生一个小小的疑惑：那你放就放呗， `MethodInvocation oldInvocation = invocation.get();` 这个操作是啥意思？原本就没有，你 `get` 个什么劲呢？？？

哎？真的没有吗？如果是一个 AOP 代理对象，调用了另外一个 AOP 代理对象的话，这个过程是在一个线程中执行的呀，那第二个代理对象的方法被调用时，是不是也会经过 `ExposeInvocationInterceptor` 呢？那是不是从 `ThreadLocal` 中就可以取出 `MethodInvocation` 了呢？所以小伙伴们一定要多想一层呀，多实践多思考才会更进步 \~

### 1.2 createProxy

上面结束之后，所有的增强器也就都准备好了，接下来就是创建代理对象的部分了，咱进入 `createProxy` 中：

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

    // 根据AOP的设计，决定是否强制使用Cglib
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            // Cglib动态代理直接记录被代理bean的所属类即可
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            // 解析被代理bean所属类的所有实现的接口
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    // 1.2.1 构造整合所有增强器
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    // 1.2.2 创建代理对象
    return proxyFactory.getProxy(getProxyClassLoader());
}
```

到了这里，咱就可以发现，这里面的逻辑已经基本上处理的差不多了，核心的动作就两个：**收集整理要织入到目标对象的通知增强器**，以及**创建代理对象**。前面的那些小细节小伙伴们可以自行研究，相对都是蛮简单的，小册带小伙伴们关注的是这两部分的核心逻辑。

#### 1.2.1 buildAdvisors

源码不算长，里面有一段日志的部分，小册在这里删掉了，咱只关心核心逻辑：

```java
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
    // Handle prototypes correctly...
    // 这个地方是适配Spring原生AOP的MethodInterceptor，感兴趣的小伙伴可自行研究
    Advisor[] commonInterceptors = resolveInterceptorNames();

    List<Object> allInterceptors = new ArrayList<>();
    if (specificInterceptors != null) {
        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));
            }
        }
    }
    // logger ......

    Advisor[] advisors = new Advisor[allInterceptors.size()];
    for (int i = 0; i < allInterceptors.size(); i++) {
        // 此处有一个原生AOP的适配动作
        advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
    }
    return advisors;
}
```

上面整合 SpringFramework 原生 AOP 的内容咱小册就不提及了，毕竟是很久之前用的东西了，咱现在都是 AspectJ 的。在最下面，它有一个 `advisorAdapterRegistry.wrap` 的方法调用，它是干嘛的呢？咱可以去瞅一眼：

```java
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    // Advisor增强器可以直接返回
    if (adviceObject instanceof Advisor) {
        return (Advisor) adviceObject;
    }
    // 不支持非Advice的类型
    if (!(adviceObject instanceof Advice)) {
        throw new UnknownAdviceTypeException(adviceObject);
    }
    Advice advice = (Advice) adviceObject;
    // MethodInterceptor的支持
    if (advice instanceof MethodInterceptor) {
        // So well-known it doesn't even need an adapter.
        return new DefaultPointcutAdvisor(advice);
    }
    // AdvisorAdapter的支持
    for (AdvisorAdapter adapter : this.adapters) {
        // Check that it is supported.
        if (adapter.supportsAdvice(advice)) {
            return new DefaultPointcutAdvisor(advice);
        }
    }
    throw new UnknownAdviceTypeException(advice);
}
```

注意这个方法的参数和返回值：它可以是任意类型的入参，但返回的一定是 `Advisor` ，这也就呼应了 `wrap` 方法的含义：**将可以支持转换 / 包装为** `**Advisor**` **类型的对象适配成** `**Advisor**` 。至于它可以适配的类型，内置的只有 `MethodInterceptor` 和几种原生的 `Advice` （前面 Spring 原生 AOP 中提到的），不过它提供了一个 `AdvisorAdapter` 的接口，供我们扩展使用，以此来支持自定义的 `Advice` 类型。不过我们几乎都没有这么做的，所以这部分小伙伴们知道一下就可以了，没必要深究。

#### 1.2.2 proxyFactory.getProxy

下面就是真正创建代理对象的逻辑了，这个方法又分为两个部分：

```java
public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}
```

咱一一来看。

**1.2.2.1 createAopProxy**

```java
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` 这个类中使用，咱们开发也基本不会碰这些东西，所以这个咱可以跳过了，关键的还是下面 `getAopProxyFactory().createAopProxy(this);` 的执行。

`getAopProxyFactory` 方法返回的是当前 `ProxyCreatorSupport` 的成员 `aopProxyFactory` ，借助 Debug 可以发现它的类型是 `DefaultAopProxyFactory` 。

![img](https://cdn.nlark.com/yuque/0/2022/png/229542/1671542687306-0af83f35-0962-4cac-b93a-aed6bd6ab6df.png)

进入到它的 `createAopProxy` 方法中，终于发现了咱熟悉的 jdk 、Cglib 动态代理的字眼了：

```java
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: " +
                    "Either an interface or a target is required for proxy creation.");
        }
        // 如果要代理的本身就是接口，或者已经是被jdk动态代理了的代理对象
        // 则使用jdk动态代理
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        // 否则使用Cglib动态代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}
```

至此，咱就知道，使用 jdk 动态代理，还是 Cglib 动态代理，底层的选择是在这里决定的。

**1.2.2.2 AopProxy#getProxy**

创建完 `AopProxy` 后，下面就是创建代理对象的动作了，咱以 `JdkDynamicAopProxy` 为例进去看一下：

```java
public Object getProxy(@Nullable ClassLoader classLoader) {
    // logger ......
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // jdk动态代理的API
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
```

看，最底下，咱最最熟悉的 `Proxy.newProxyInstance` 方法出现了！！！所以由此咱就可以体会到，代理对象的底层创建还是依赖 jdk 动态代理，或者 Cglib 动态代理的核心 API 呀！

至于 Cglib 动态代理的创建，咱就不特别深入了，咱注意一下中间的核心部分即可：

```java
    // ......
    // Configure CGLIB Enhancer...
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
        enhancer.setClassLoader(classLoader);
        if (classLoader instanceof SmartClassLoader &&
                ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
        }
    }
    enhancer.setSuperclass(proxySuperClass);
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
        types[x] = callbacks[x].getClass();
    }
    // fixedInterceptorMap only populated at this point, after getCallbacks call above
    enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);

    // Generate the proxy class and create a proxy instance.
    return createProxyClassAndInstance(enhancer, callbacks);
    // ......
```

可以看到，这也是对 Cglib 中的 `Enhancer` 进行操作，核心的思路是不变的，只是框架比咱考虑的更多罢了。

OK ，到此为止，代理对象也就成功创建了，整个 AOP 通知织入的流程也就结束了。
