Spring AOP 知识点

之前看了王福强老师的《Spring揭秘》一书,对Spring AOP有了一个概念,但是毕竟版本比较老,无法与现在的框架使用相结合,然后又看了尚硅谷雷神的Spring注解开发的视频,跟着和源码走了一遍,突然觉得和王福强老师的《Spring 揭秘》就结合起来了,一种豁然开朗的感觉,因此写了这样一篇博客,写的不好的地方请见谅

Spring AOP 知识点总结

AOP 中的概念

AOP,面向切面编程,其中有以下的概念:

  • JoinPoint:切入点,即在什么时间点织入其他的逻辑,虽然有很多类型的织入,如方法执行,方法调用,字段设置等,理论上系统的每个点都可以作为切入点,但是Spring AOP仅仅支持方法执行的织入,这已经能满足80%的需要了

  • Pointcut:用来描述JoinPoint的,比如说AspectJexpression表达式

  • Advise:通知,即织入JoinPoint的横切逻辑,我的理解是这个东西就是在系统运行到JoinPoint的时候执行的一段代码

  • Aspect:切面,就好像面向对象的类,其中包含了PointcutAdvise

Java如何实现AOP

Java是通过代理模式来实现AOP的,代理模式其中有静态代理和动态代理,主要使用的是动态代理。动态代理又分为两种,JDK自带的基于接口的动态代理和CGLIB的基于子类的动态代理

JDK提供的动态代理主要有一个类和一个接口组成,即java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口,Proxy类用来生成动态代理实例,而InvocationHandler用于实现调用逻辑。由于这种方式是基于接口的,因此,如果一个类没有实现任何接口,就无法使用这种方式了

CGLIB是通过动态字节码生成技术,为需要代理的目标对象动态生成一个子类来进行扩展。这种方式主要使用的是net.sf.cglib.proxy.MethodInterceptor接口。由于这种方式是基于子类的,因此,如果代理的方法是是子类无法重写的,如private\final等,则无法完成代理

Spring AOP中关于AOP各个概念的实现

Pointcut

Spring AOP 定义了org.springframework.aop.Pointcut接口作为所有的Pointcut的顶层抽象

public interface Pointcut {
    
    ClassFilter getClassFilter();
    
    MethodMathcher getMethodMatcher();
    
    Point True = TruePointcut.INSTANCE;
    
}

ClassFilterMethodMatcher 分别匹配织入操作的对象和方法,前面提过,Spring AOP仅支持方法执行的织入,因此需要定位一个方法,就需要从类,方法签名两个方面来进行匹配

ClassFilter

ClassFilter 接口的作用就是对JoinPoint进行类级别的匹配,以下是ClassFilter接口的定义

public interface ClassFilter {
    
    boolean matches(Class clazz);
    
    ClassFilter true = TrueClassFilter.INSTANCE;
    
}

可以看到,ClassFilter接口中只有一个matches方法,传入参数是一个Class对象,返回值为布尔类型,如果类中的方法需要进行织入逻辑的时候,那么往matches方法传入该类的Class对象就会返回true

MethodMatcher

MethodMatcher接口顾名思义,就是只有匹配的方法才会进行AOP织入的逻辑,下面是MethodMatcher接口的定义

public interface MethodMatcher {
    
    boolean matches(Method method, Class targetClass);
    
    boolean isRuntime();
    
    boolean matches(Method method, Class targetClass, Object[] args);
    
    MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}

可以看到,该接口有三个方法,其中还有两个同名的matches方法进行重载,它俩的区别就在于是否需要对织入的方法进行更精细的控制。这两个matches方法的分界线就在于isRuntime方法,如果isRuntime方法返回true,那么有三个参数的matches方法就会被调用,三个参数的matches方法多出来的参数就是方法调用时传入的参数

执行逻辑如下描述:

  • 首先执行两个参数的matches方法,如果该方法返回false,说明不需要织入,直接结束判断;如果该方法返回true,再调用isRuntime方法
  • 如果isRuntime方法返回false,说明该方法需要切入,结束判断;如果isRuntime方法返回true,说明还需要进行参数的检查,接着调用三参数的matches方法
  • 如果三参数的matches方法返回true,需要切入,反之则不需要

按照isRuntime方法的返回值,MethodMatcher也分为了两种类型,isRuntime返回falseMethodMatcher称为StaticMethodMatcher,相对的其它MethodMatcher称为DynamicMethodMatcherStaticMethodMatcher的性能会比较高,因为可以把结果缓存起来,而DynamicMethodMatcher因为每次都要根据方法调用传入的参数进行判断,所以无法缓存,性能比较差

Pointcut实现类

基于上述的MethodMatcher类型,Pointcut也分为了两类,即StaticMethodMatcherPointcutDynamicMethodMatcherPointcut,以下是其中的一些实现类列举,具体实现可以查看源码

  • NameMatchMethodPointcut
  • JdkRegexpMethodPointcut
  • AnnotationMatchingPointcut
  • ComposablePointcut
  • ControlFlowPointcut

如果Spring AOP提供的Pointcut实现类无法满足需要,可以自定义Pointcut

Advice

Spring AOP中的Advice顶级接口定义是org.aopalliance.aop.Adivce接口,该接口是一个空接口,其子接口有org.springframework.aop.AfterAdviceorg.springframework.aop.BeforeAdivceorg.aopalliance.intercept.Interceptor

public interface Advice {

}
image-20210818093226209.png

per-class类型的Advice

上图中的Advice类型都是per-class类型的,per-class类型的Advice的实例可以在目标对象类的所有实例之间共享。接下来介绍这些per-class类型Advice的定义

org.springframework.aop.MethodBeforeAdvice

public interface MethodBeforeAdvice extends BeforeAdvice {
    
    void before(Method method, Object[] args, Object target) throws Throwable;
    
}

org.springframework.aop.ThrowsAdvice

public interface ThrowsAdvice extends AfterAdvice {

}
/*
虽然该接口没有定义任何接口,但是实现该接口时候,方法定义需要遵循下面的模板。其中[]中的三个参数可以省略,这样可以根据将要拦截的Throwable的不同类型,在同一个ThrowsAdvice中实现多个afterThrowing方法
**/
void afterThrowing([Method, args, target], ThrowableSubclass);

org.springframework.aop.AfterReturningAdvice

public interface AfterReturningAdvice extends AfterAdvice {
    void afterReturning(Object returnValue, Method method, Object[] args, Object target);
}

org.aopaliance.intercept.MethodInterceptor

public interface MethodInterceptor extends Interceptor {
    
    Object invoke(MethodInvocation invocation) throws Throwable;
}

per-instance类型的Advice

没怎么见过这种类型的使用,就暂时略过了,很少见

Advisor

Spring中的Advisor通常只持有一个Pointcut和一个Advice,可以认为是一种特殊的Aspect,其中的定义为

org.springframework.aop.Advisor

public interface Advisor {

    Advice EMPTY_ADVICE = new Advice() {};
    
    Advice getAdvice();

    boolean isPerInstance();

}

Advisor中定义了两个方法,其中getAdvice用来获取Advice;而isPerInstance标识此Advice是与特定实例相关联的,但是这个方法在当前的框架中并没用使用,它总是返回true

其中Advisor有两个分支,PointcutAdvisorIntroductionAdvisor,前者为per-class类型的AdviceAdvisor,后者是per-instance类型的AdviceAdvisor,重点看一下PointcutAdvisor的定义

org.springframework.aop.PointcutAdvisor

public interface PointcutAdvisor extends Advisor {

    Pointcut getPointcut();
}

很明显其中只定义了一个方法,用来获取Pointcut

在注解开发Spring AOP中,主要的实现类就是InstantiationModelAwarePointcutAdvisorImpl,详细参考源码

image-20210819105732378.png

当某个织入点有多个横切逻辑时,注意这些逻辑的执行顺序,可能会影响系统

Spring AOP的织入

织入就是将横切逻辑集成到系统中,完成织入操作的就是织入器,Spring AOP中的织入器就是org.springframework.aop.framework.ProxyFactory,以下时该类的定义

org.springframework.aop.framework.ProxyFactory

public class ProxyFactory extends ProxyCreatorSupport {

    public ProxyFactory() {
    }

    public ProxyFactory(Object target) {
        setTarget(target);
        setInterfaces(ClassUtils.getAllInterfaces(target));
    }

    public ProxyFactory(Class<?>... proxyInterfaces) {
        setInterfaces(proxyInterfaces);
    }

    public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {
        addInterface(proxyInterface);
        addAdvice(interceptor);
    }

    public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) {
        addInterface(proxyInterface);
        setTargetSource(targetSource);
    }

    public Object getProxy() {
        return createAopProxy().getProxy();
    }

    @SuppressWarnings("unchecked")
    public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) {
        return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();
    }

    @SuppressWarnings("unchecked")
    public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) {
        return (T) new ProxyFactory(proxyInterface, targetSource).getProxy();
    }

    public static Object getProxy(TargetSource targetSource) {
        if (targetSource.getTargetClass() == null) {
            throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");
        }
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTargetSource(targetSource);
        proxyFactory.setProxyTargetClass(true);
        return proxyFactory.getProxy();
    }

}

AopProxy

要了解ProxyFactory,需要先从org.springframework.aop.framework.AopProxy说起,该接口的定义如下

public interface AopProxy {
    
    Object getProxy();
    
    Object getProxy(ClassLoader classLoader);
}

可以看到AopProxy定义了获取代理的方法。对于不同的代理实现机制,Spring AOP提供了不同的AopProxy子类实现,目前Spring AOP主要提供了JDK动态代理和CGLIB两种机制的AopProxy的实现,具体的实现参考源码

image-20210819132708505.png

上图列出了SpringAOP中的一些关键类

AopProxyFactory

各种AopProxy实例化的实现是采用了工厂模式,通过org.springframework.aop.framework.AopProxyFactory来进行,其中AopProxyFactory的接口定义如下,它只有一个实现类,即org.springframework.aop.framework.DefaultAopProxyFactory

org.springframework.aop.framework.AopProxyFactory

public interface AopProxyFactory {
    
    AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}

可以看到AopProxyFactory通过AdvisedSupport来创建一个AopProxy

其中DefaultAopProxyFactory的实现逻辑也很简单

if (!NativeDetector.isNativeImage() && (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
    // 创建CglibAopProxy实例返回
} else {
    // 创建JdkDynamicAopProxy实例返回
}

以上逻辑可以看到,如果当前JVM运行环境不是GraalVM并且满足以下条件之一就使用CGLIB

  • AOP配置中optimize参数为true
  • AOP配置中proxyTargetClass参数为true
  • 用户没有提供代理接口

AdvisedSupport

image-20210818102845528.png

上图展示了AdvisedSupport继承了ProxyConfig类,实现了Advised接口

AdvisedSupport其实就是一个生成代理对象所需要的信息的载体,其中的信息可以分为两类,一类是以org.springframework.aop.framework.ProxyConfig,它记载了生成代理对象的控制信息;一类是以org.springframework.aop.framework.Advised,它承载了生菜代理对象所需要的必要信息,如目标类、Advice、Advisor

以下是ProxyConfig的定义信息,其中定义了5个boolean类型的变量

org.springframework.aop.framework.ProxyConfig

private boolean proxyTargetClass = false;

private boolean optimize = false;

boolean opaque = false;

boolean exposeProxy = false;

private boolean frozen = false;
  • proxyTargetClass:如果该属性为true,那么ProxyFactory将会使用CGLIB对目标对象进行代理

  • optimize:如果该属性为true,则表示代理对象需要采取进一步的优化措施,如代理对象生成后,代理信息发生了改变,代理对象是否可以忽略这些变动。相应的,如果该属性为trueProxyFactory也会使用CGLIB代理

  • opaque:控制生成的代理对象是否可以强制转化成Advised,默认是false,即可以强制转化。通过强制转化成Advised,可以查询到代理对象的一些状态

  • exposeProxy:该属性控制SpringAOP在生成代理对象时,是否将代理对象绑定到ThreadLocal上。如果目标对象需要访问当前代理对象,可以通过AopContext.currentProxy()取得,常用于事务

  • frozen:如果frozentrue,说明一旦为代理对象生成的各项信息配置完成,则不允许修改

除了ProxyConfig提供的控制信息以外,还需要生成代理对象的一些具体信息,其中包括需要代理的目标类,横切逻辑等,这些信息就包含在Advised

image-20210819133929367.png

上图中ProxyCreatorSupport类,抽取了一些公用的逻辑,子类可以根据需要重写方法。ProxyCreatorSupport持有了一个DefaultAopProxyFactory对象,用它来生成各种AopProxy

public class ProxyCreatorSupport extends AdvisedSupport {
    
    private AopProxyFactory aopProxyFactory;
    
    protected final synchronized AopProxy createAopProxy() {
        if (!this.activate) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }
}

除了ProxyFactory以外,ProxyCreatorSupport还有其他的子类

image-20210818130033773.png

ProxyFactoryBean

ProxyFactoryBeanSpringAOPSpring容器的一个桥梁,它专门用来生产Proxy,需要注意的是,ProxyFactoryBean正确的断句应该是Proxy+FactoryBean,即它产生的对象是Proxy,而不是ProxyFactory

ProxyFactoryBean的实现并不复杂,直接从父类的createAopProxy方法创建代理对象返回即可。既然是一个FactoryBean,那么就需要关注它的getObject()方法了

public Object getObject() throws BeansException {
    initializeAdvisorChain();
    if (isSingleton()) {
        return getSingletonInstance();
    }
    else {
        if (this.targetName == null) {
            logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the 'targetName' property.");
        }
        return newPrototypeInstance();
    }
}

FactoryBean定义中要求标明返回的对象是singleton还是prototype,针对这两种情况会返回不同的代理对象。如果isSingleton方法返回true,则会通过singleInstance(Object类型)缓存生成的代理对象

ProxyFactoryBean在继承父类ProxyCreatorSupport的所有配置属性外,还有几个额外的属性

  • proxyInterfaces:配置需要代理哪些接口。即使不指定,ProxyFactoryBean也可以自动检测目标对象所实现的接口来进行代理,这个功能由autodetectInterfaces属性来控制
  • interceptorNames:这个属性用来指定多个将要织入目标对象的Advice,拦截器以及Advisor。这样就不需要像ProxyFactory那样通过addAdviceaddAdvisor方法一个一个的添加了。
    • 如果没有为ProxyFactoryBean显式的指定目标对象,则可以在interceptorNames的最后一个位置放目标对象的bean定义名称。最好别用
    • interceptorNames支持采用 * 通配符的方式来设置Advisors
  • singleton:控制是否以单例的模式返回代理对象

自动代理机制

虽然可以使用ProxyFactory或者ProxyFactoryBean来创建AOP代理,但是每一个目标对象都需要一个ProxyFactory或者ProxyFactoryBean,在目标对象很多的情况下,工作量是难以想象的。因此Spring AOP给出了自动代理的机制

原理

自动代理的实现原理是基于BeanPostProcessor概念之上的,只要提供一个BeanPostProcessor,在其中实现一个逻辑,当对象实例化的时候,为其生成代理对象并返回,而不是实例化后的目标对象本身,即可完成自动代理

伪代码示例如下:

for (bean in SpringContainer) {
    if (符合拦截条件) {
        return createProxyFor(bean);
    } else {
        return createInstance(bean);
    }
}

因此现在的重点就在于如何定义拦截条件以及如何将拦截条件告知给自动代理的实现类

  • 可以通过外部配置文件传入这些拦截信息
  • 可以通过注解在代码中标注Pointcut拦截信息

可用的AutoProxyCreator

image-20210818135542212.png

可以看到,AutoProxyCreator都是ProxyConfig的子类,因为ProxyConfig中定义了生成代理对象的控制信息

TargetSource

TargetSource就是一个目标类的包装,在创建AOP代理时,除了可以直接指定目标类的class对象,指定目标类的beanName外,还可以传入一个TargetSource。最常用的TargetSource就是SingletonTargetSource

分析AOP代理的创建过程

我们使用AOP的时候,往往就是通过在配置类中加上@EnableAspetJAutoProxy注解,之后只需要用@Aspect放在自己的切面类上,再在切面类中定义横切逻辑的方法,使用诸如@Pointcut、@Before、@AfterReturning等等注解定义PointcutAdvised即可完成AOP的编程,下面就来分析这些是如何完成的

@EnableAspectJAutoProxy

首先看一下@EnableAspectJAutoProxy的源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;

}

可以看到其中有两个属性proxyTargetClassexposeProxy,这就是前面提到的ProxyConfig中定义的属性。此外,还通过@Import注解导入了AspectJAutoProxyRegistrar类,这个类的作用就是往容器中注入前面提到的AutoProxyCreator来帮我们进行自动代理,我们来看看AspectJAutoProxyRegistrar类的源码

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        // 往容器中注册自动代理类,AutoProxyCreator
        // 往下追溯,其实就是注入了一个AnnotationAwareAspectJAutoProxyCreator
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        // 这里是获取配置类中的EnableAspectJAutoProxy注解的信息
        // 也就是上面看到的proxyTargetClass和exposeProxy
        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        
        // 这里是根据EnableAspectJAutoProxy注解中的信息设置AutoProxyCreator的值
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

}

接下来重点关注一下AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)方法

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    BeanDefinitionRegistry registry, @Nullable Object source) {
    // 可以看到这里就是往容器中注入了AnnotationAwareAspectJAutoProxyCreator
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
    Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    
    /* 
    判断registry中是否已经有一个AUTO_PROXY_CREATOR_BEAN_NAME的beanDefinition
        没有——>在后面会放一个AnnotationAwareAspectJAutoProxyCreator的定义信息
        有
            判断是否是AnnotationAwareAspectJAutoProxyCreator的Bean定义
                不是
                    判断二者之间优先级,注入优先级高的那个
    源代码中AnnotationAwareAspectJAutoProxyCreator的优先级是最高的,因此,最后都会注入这个Bean
    **/
    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;
    }

    // 这里是如果registry中没有定义名为AUTO_PROXY_CREATOR_BEAN_NAME的bean,则注入
    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;
}

至此,可以看到,@EnableAspectJAutoProxy的作用就是往容器中注入了一个AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator

首先需要注意的是AnnotationAwareAspectJAutoProxyCreator实现了Ordered、BeanFactoryAware、SmartInstantiationAwareBeanPostProcessor接口,注意不是直接实现的,父类实现了这些接口,这些接口在后面会用到

实现的接口方法

setBeanFactory()方法流程

先来分析AnnotationAwareAspectJAutoProxyCreator的创建流程,因为AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessorSmartInstantiationAwareBeanPostProcessorBeanPostProcessor的子接口),所以它的实例化是在AbstractApplicationContext中的registerBeanPostProcessors方法中完成的,它的实例化就是正常的Bean的流程

因为AnnotationAwareAspectJAutoProxyCreator实现了BeanFactoryAware接口,所以先看看它的setBeanFactory方法

//==========AbstractAutoProxyCreator==========
public void setBeanFactory(BeanFactory beanFactory) {
    this.beanFactory = beanFactory;
}


//==========AbstractAdvisorAutoProxyCreator=====
public void setBeanFactory(BeanFactory beanFactory) {
    super.setBeanFactory(beanFactory);
    if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
        throw new IllegalArgumentException(
            "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
    }
    initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}


//==========AnnotationAwareAspectJAutoProxyCreator=====
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    super.initBeanFactory(beanFactory);
    if (this.aspectJAdvisorFactory == null) {
        this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
    }
    this.aspectJAdvisorsBuilder =
        new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}

AnnotationAwareAspectJAutoProxyCreator并没有直接实现setBeanFactory方法,而是继承了父类的实现,其中在父类实现的setBeanFactory方法中又调用了initBeanFactory方法,而AnnotationAwareAspectJAutoProxyCreator则重写了这个方法

可以看到,在回调BeanFactoryAware接口的方法过程中,AnnotationAwareAspectJAutoProxyCreator主要的工作就是初始化了三个类,分别是BeanFactoryAdvisorRetrievalHelperAdapterReflectiveAspectJAdvisorFactoryBeanFactoryAspectJAdvisorsBuilderAdapter,它们的作用如下

  • BeanFactoryAdvisorRetrievalHelperAdapterBeanFactoryAdvisorRetrievalHelper的子类,用于从 BeanFactory检索标准的Spring Advisor,用于自动代理
  • ReflectiveAspectJAdvisorFactoryAspectJAdvisorFactory接口的实现类,它可以从BeanFactory检索遵循AspectJ注解语法的类中,来创建Spring AOP代理,使用反射来调用相应的Advise
  • BeanFactoryAspectJAdvisorsBuilderAdapterBeanFactoryAspectJAdvisorsBuilder的子类,用于从BeanFactory检索@Aspect标注的类,并基于它们构建 Spring Advisors,用于自动代理

postProcessBeforeInstantiation方法

SmartInstantiationAwareBeanPostProcessorInstantiationAwareBeanPostProcessor的子接口,而InstantiationAwareBeanPostProcessor中定义了在Bean实例化前后的回调,注意和BeanPostProcessor的区别,BeanPostProcessor定义的是Bean初始化前后的回调,在调用BeanPostProcessor之前,Bean已经完成了初始化,并且已经完成了属性赋值,接下来就是调用init方法,而BeanPostProcessor的回调就发生在init方法的前后

所以我们主要看其中的回调方法,首先看postProcessBeforeInstantiation方法

// 请注意,AnnotationAwareAspectJAutoProxyCreator并没有重写这个方法,该方法是在AbstractAutoProxyCreator中
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    
    /* 这里根据beanClass和beanName创建一个缓存的key值,这在之后做缓存时需要用到
        其实就是要么返回beanName,要么返回beanClass
    **/
    Object cacheKey = getCacheKey(beanClass, beanName);

    /*
    adviseBeans中保存了对象是否需要被代理的信息,它是Map<Object, Boolean>类型的
    如果该对象被代理了,则其对应的布尔值为true,反之为false
    
    如果该对象已经在adviseBeans中了,说明之前已经走过了流程,所以不需要再继续,直接返回
    如果对象是AOP相关的基础类,如Advisor,Advise,Pointcut,则说明不需要代理,直接掠过
    如果对象是@Aspect注解的类,也是直接略过的
    
    关于isInfrastructureClass和shouldSkip方法的逻辑,之后详述
    **/
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    /*
    如果我们定义了TargetSourceCreator,将会在此处创建代理
    防止目标bean的不必要的默认实例化,TargetSource将以自定义方式处理目标实例
    如果没有,那么在前置处理的流程中不会创建代理,直接返回null
    
    当然,按照惯用的使用注解开发AOP的流程,这一步一般是走不到的,即不会在前置处理中创建代理
    **/
    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;
}

postProcessAfterInitialization方法

接下来看看实例化后的处理逻辑,postProcessAfterInitialization方法

// 该方法同样是在AbstractAutoProxyCreator中
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // 关键的方法在这里wrapIfNecessary方法
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
//==========AbstractAutoProxyCreator==========
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 这里如果targetSourcedBeans中包含了beanName,说明已经在前置处理中进行了代理
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // 这里说明它不需要代理
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    // 这里和before中的处理一致
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    /*
    这里通过getAdvicesAndAdvisorsForBean方法查询到bean的所有的Advisor和Advice
    如果没有查询到,那说明不需要代理,在缓存中记录一下,将bean原样返回即可
    如果查询到Advices和Advisors,则创建代理,记录缓存,返回代理对象
    **/
    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;
}

判断一个bean是否应该直接跳过的方法

isInfrastructureClass方法

isInfrastructureClass方法是判断一个类是否是AOP的基础类的方法,以下是其方法定义

// ==========AbstractAutoProxyCreator==========
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;
}


// AnnotationAwareAspectJAutoProxyCreator重写了isInfrastructureClass方法
/*
可以看到该方法就是在父类判断的基础上增加了对注解@Aspect的判断
如果一个类之上加上了@Aspect,也属于AOP的基础类
*/
protected boolean isInfrastructureClass(Class<?> beanClass) {
    return (super.isInfrastructureClass(beanClass) ||
            (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}

shouldSkip方法

这个类用来判断是否应该跳过该bean,不对此Bean做代理,该方法其实就是跳过那些加了Aspect注解的Bean

shouldSkip方法中调用了findCandidateAdvisors方法获取了容器中所有的Advisor,然后看这些Advisor的对应的beanName是否和此次需要判断的名字相同,如果相同就跳过

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    /* 
    可以看到,这里其实是先找到系统中所有的Advisor
    然后依次判断bean是否就是这些Advisor,如果是,则可以略过,否则调用父类的shouldSkip
    **/
    // TODO: Consider optimization by caching the list of the aspect names
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
            return true;
        }
    }
    return super.shouldSkip(beanClass, beanName);
}

// ==========AbstractAutoProxyCreator==========
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 该方法其实就是判断beanName是否是以beanClass的全限定名开始,以“.ORIGINAL”结尾
    return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}

找到并构建Advisor的方法

findCandidateAdvisors

// ==========AbstractAutoProxyCreator==========
protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    return this.advisorRetrievalHelper.findAdvisorBeans();
}


// AnnotationAwareAspectJAutoProxyCreator重写了这个findCandidateAdvisors方法
// ==========AnnotationAwareAspectJAutoProxyCreator==========
protected List<Advisor> findCandidateAdvisors() {
    // 调用父类的findCandidateAdvisors方法,获取Spring的标准Advisor
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 从BeanFactory中构建所有的AspectJ的切面,添加到advisors中
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

这个方法的逻辑很简单,先从调用父类的同名方法,获取到Spring的标准Advisor,再调用自己的方法,构建所有的以@Aspect标注的切面类,接下来就看看这两个方法是怎么找到所有的Advisor

advisorRetrievalHelper.findAdvisorBeans

先来看看父类是怎么做的,这个advisorRetrievalHelper是保存在AbstractAdvisorAutoProxyCreator中的,是BeanFactoryAdvisorRetrievalHelperAdapter类型的,它的初始化是在setBeanFactory中的,忘记的话可以看前面关于BeanFactoryAware接口的流程,这个方法是去找到容器中用标准的方式(接口实现)实现的所有Advisor

AbstractAdvisorAutoProxyCreator中定义了BeanFactoryAdvisorRetrievalHelperAdapter类继承了BeanFactoryAdvisorRetrievalHelper,并重写了其isEligibleBean方法,该方法的作用就是判断给定的bean名称的切面类是否有资格作为一个切面类来使用,如果没有资格,则不会将其当作Aspect对待

private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {

    public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
        super(beanFactory);
    }

    @Override
    protected boolean isEligibleBean(String beanName) {
        return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
    }
}

可以看到isEligibleBean中又调用了AbstractAdvisorAutoProxyCreatorisEligibleAdvisorBean方法,以下是该方法的源码,这个方法永远返回true,子类可以根据需要重写这个方法

// ==========AbstractAdvisorAutoProxyCreator==========
protected boolean isEligibleAdvisorBean(String beanName) {
    return true;
}

接下来就可以分析findAdvisorBeans方法了,以下是findAdvisorBeans的源码

public List<Advisor> findAdvisorBeans() {
    
    /* 
    这里存储了所有的advisor类型的bean的名称
    如果advisorNames为空,说明还没有进行从beanFactory中找advisor的流程
    **/
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
        /* 
        从BeanFactory中找到所有Advisor及其子类的beanName,将其赋值给advisorNames
        不要在这里初始化FactoryBean,我们需要让auto-proxy应用在所有的常规bean
        **/
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }

    // 这里根据上面找到的beanName,创建对应的Advisor
    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
        // 先判断这个beanName是否有资格作为切面类使用
        if (isEligibleBean(name)) {
            // 如果这个bean还在创建中,先跳过
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                try {
                    // 从beanFactory中获取这个Bean,放到advisors中
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    /* 
                    如果抛出的异常时BeanCurrentlyInCreationException,则先跳过,说明这个对象的依赖还没到位
                    如果是其他异常,抛出该异常
                    **/
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        String bceBeanName = bce.getBeanName();
                        if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Skipping advisor '" + name +
                                             "' with dependency on currently created bean: " + ex.getMessage());
                            }
                            // Ignore: indicates a reference back to the bean we're trying to advise.
                            // We want to find advisors other than the currently created bean itself.
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
    }
    return advisors;
}

aspectJAdvisorsBuilder.buildAspectJAdvisors

这个aspectJAdvisorBuilder对象是保存在AnnotationAwareAspectJAutoProxyCreator中的,它的类型是BeanFactoryAspectJAdvisorsBuilderAdapter,它是BeanFactoryAspectJAdvisorsBuilder的子类,以下是它的源码,可以看到它重写了父类的isEligibleBean方法,调用了AnnotationAwareAspectJAutoProxyCreatorisEligibleAspectBean方法

这个方法的主要作用是找到容器中以@Aspect注解实现的切面类,构造对应的Advisor

private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {

    public BeanFactoryAspectJAdvisorsBuilderAdapter(
        ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {

        super(beanFactory, advisorFactory);
    }

    @Override
    protected boolean isEligibleBean(String beanName) {
        return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
    }
}

以下是AnnotationAwareAspectJAutoProxyCreatorisEligibleAspectBean方法。该方法的判断方式就是根据includePatterns来匹配BeanName

// ==========AnnotationAwareAspectJAutoProxyCreator==========
protected boolean isEligibleAspectBean(String beanName) {
    if (this.includePatterns == null) {
        return true;
    }
    else {
        for (Pattern pattern : this.includePatterns) {
            if (pattern.matcher(beanName).matches()) {
                return true;
            }
        }
        return false;
    }
}

接下来就看看buildAspectjAdvisors方法的源码

public List<Advisor> buildAspectJAdvisors() {
    // 先从aspectBeanNames找到缓存的切面类的名称
    List<String> aspectNames = this.aspectBeanNames;

    // 单例模式中的双重检查
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                // 从beanFactory中获取所有的beanName,遍历
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                    // 判断是否有资格成为一个切面类
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }
                    // 获取beanName的类型
                    // 我们必须要小心,不要实例化了bean,此时它们还不会被代理
                    // We must be careful not to instantiate beans eagerly as in this case they
                    // would be cached by the Spring container but would not have been weaved.
                    Class<?> beanType = this.beanFactory.getType(beanName, false);
                    if (beanType == null) {
                        continue;
                    }
                    /* 
                    判断它的上面是否加了Aspect注解,如果加了该注解,先将其beanName放到aspectNames中
                    然后遍历其beanName上的所有方法,对于加了@Before等的方法,创建一个对应的Advisor
                    如果创建的Advisor是单例模式的,则将其存放到advisorsCache中
                    否则将其对应的工厂对象放到aspectFactoryCache中,之后会从中取出来创建Advisor
                    
                    将创建的Advisor放到advisors中,返回
                    **/
                    if (this.advisorFactory.isAspect(beanType)) {
                        aspectNames.add(beanName);
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            /**
                            MetadataAwareAspectInstanceFactory的作用就是创建指定beanName的Advisor
                            **/
                            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));
                        }
                    }
                }
                this.aspectBeanNames = aspectNames;
                return advisors;
            }
        }
    }

    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    /** 
    如果aspectNames不为空,则遍历所有的aspectName,尝试从advisorsCache中获取其对应的Advisor
    如果没有获取到Advisor,则尝试创建
    **/
    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;
}

advisorFactory.getAdvisors

这个方法的作用是从@Aspect标注的类中,为每个使用@Before@AfterThrowing等等注解标注的方法创建一个对应的Advisor,然后会返回这样一个Advisor的集合,现在来分析一下这个方法的流程

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    /**
    这里先取出切面类和它的beanName,然后进行校验
    校验主要校验两个方面:
        第一是切面类的父类不能也被@Aspect标注,且其不是抽象类
        第二是这个切面类的类型是否被SpringAOP支持
    **/
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    validate(aspectClass);

    // 这里是包装一下MetadataAwareAspectInstanceFactory,让它只实例化一次
    // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
    // so that it will only instantiate once.
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
        new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    /**
    这里的getAdvisorMethod的逻辑就是遍历切面类的所有方法,找出所有的没有被@Pointcut标注的方法
    此外如果切面类还有父类,接口,同样会遍历找到父类和接口中的方法
    **/
    List<Advisor> advisors = new ArrayList<>();
    for (Method method : getAdvisorMethods(aspectClass)) {
        /** 
        这里就是遍历得到的方法,然后创建Advisor,添加到advisors
        
        这个方法源码上加了一段注释,在Springframework5.2.7之前,会使用advisors.size()替换
        下面这个硬编码的0,详细看源码注释
        **/
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // If it's a per target aspect, emit the dummy instantiating aspect.
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }

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

    return advisors;
}

advisorFactory.getAdvisor

现在再来看看Advisor是怎么创建的,它的源码如下

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {

    // 这里和上面的一样,检验一下切面类
    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

    // 这里就是取出注解信息中的Pointcut值,如果为空,就直接返回一个null,
    // 这里就可以过滤掉哪些没有加注解的方法
    AspectJExpressionPointcut expressionPointcut = getPointcut(
        candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }
    
    // 这里就是构造一个InstantiationModelAwarePointcutAdvisor,这个在前面的Advisor体系中提到过
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

创建代理的相关方法

wrapIfNecessary方法

这个方法的主要作用就是判断bean是否需要创建代理,如果需要,则调用createProxy来创建代理

// ==========AbstractAutoProxyCreator==========
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;
    }

    // 这里是找到可以用在该bean中的所有advisor,如果不为空,就为其创建代理
    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;
}
// ==========AbstractAdvisorAutoProxyCreator==========
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();
}
// ==========AbstractAdvisorAutoProxyCreator==========
/**
    可以看到找的流程也很熟悉
    1. 首先找到所有的Advisor,也是通过findCandidateAdvisors方法实现的
    2. 遍历所有的Advisor,看它是否能用在这个这个Bean上
        具体而言,前面提过,对于注解开发的Advisor,返回的都是
        InstantiationModelAwarePointcutAdvisor,而它就是一个PointcutAdvisor
        对于PointcutAdvisor,会有一个Pointcut用来匹配一个类是否应该被代理
        详细信息可以回顾一下前面的Pointcut,这里简单说明
        
    Pointcut有两个层次的匹配,类级别的匹配和方法级别的匹配,所以这里的逻辑就是:
    1. 首先尝试用类匹配器匹配类,如果匹配不上,该类不需要代理,否则使用方法匹配器继续
    2. 遍历目标类所有的方法,用方法匹配器匹配,只要有一个匹配上了,就说明该目标类需要代理
    需要留意的是,在进行方法匹配时,会将目标类的父类方法和接口方法都匹配一遍
**/
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;
}

createProxy方法

最后就是创建代理了

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                             @Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    // 这里又能看到熟悉的ProxyFactory
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    /**
    这里判断是否采用CGLIB代理,判断的方式是:
    从beanDefinition中查看是否有属性名为org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass
    且其值为true的
    **/
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    /** 
    构建advisors,准确的说应该是合并
    auto-proxy-creator中可以指定拦截器(Advisor),这些拦截器应该作用到所有的代理类中
    这里就是将公共的拦截器与目标类的特定拦截器合并,然后创建代理
    **/
    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);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容