# 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 通知织入的流程也就结束了。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET 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?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
