SpringAOP原理

Spring AOP原理

@EnableAspectJAutoProxy

首先来看 @EnableAspectJAutoProxy 这个注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	// 使用cglib代理 	
    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;

}

可以看到他导入了一个 AspectJAutoProxyRegistrar 组件,AspectJAutoProxyRegistrarImportBeanDefinitionRegistrar的实现类,前面我们说过可以通过实现 ImportBeanDefinitionRegistrar 接口的方式向容器中注册 BeanDefinition

于是,在接下来的环节中:

@Override
public void registerBeanDefinitions(
      AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

    AnnotationAttributes enableAspectJAutoProxy =
        AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    if (enableAspectJAutoProxy != null) {
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}
// AopConfigUtils
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {

        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

可以看到这里其实是注入了一个 AnnotationAwareAspectJAutoProxyCreator

因此我们可以得出结论:@EnableAspectJAutoProxy 注解其实就是通过 @Import 向容器中注册了一个AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator

我们先来一起看一下类图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gfN73Rn-1625460544047)(D:\学习\001-张帅鹏面试\05-框架\AnnotationAwareAspectJAutoProxyCreator类图.png)]

可以看到,AnnotationAwareAspectJAutoProxyCreator 是 BeanFactoryAware 和 SmartInstantiationAwareBeanPostProcessor 的子类

那么,从这里我们就可以得知它的执行时机:

  1. BeanFactoryAware:在bean的实例化过程中的 initializeBean() 方法中的第一步,invokeAwareMethod(),处理Aware接口的回调

  2. SmartInstantiationAwareBeanPostProcessor

    1. AbstractAutowireCapableBeanFactory 中 createBean() 方法的这一行,即在执行doCreateBean() 之前,InstantiationAwareBeanPostProcessor有机会返回Bean实例,如果是第一次执行则返回为空。
    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    // 第一个执行时机
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    
    1. 在执行Bean自定义初始化方法的前后执行 before 和 after 方法

      protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
          ...
          invokeAwareMethods(beanName, bean);
          ...
          // 第二个执行时机
          wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
          ...
          invokeInitMethods(beanName, wrappedBean, mbd);
          ....
          // 第三个执行时机
          wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
      }
      

现在我们知道了 AnnotationAwareAspectJAutoProxyCreator 的执行时机,那么接下来就一起看一下 AOP 代理是如何创建的。

resolveBeforeInstantiation(beanName, mbdToUse)

AbstractApplicationContext.refresh() 中的 finishBeanFactoryInitialization(beanFactory) 方法用来加载剩下未实例化的单例bean,其中在执行 doCreateBean() 创建bean实例之前有最后一次机会可以返回实例bean,从而终止后面创建bean实例的过程,代码如下:

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

接下来会获取容器中所有的 InstantiationAwareBeanPostProcessor 来执行他们的 postProcessBeforeInstantiation 方法(),如果 postProcessBeforeInstantiation() 方法可以返回实例Bean,就会继续执行 postProcessAfterInstantiation() 方法。由于 AnnotationAwareAspectJAutoProxyCreator 也是 InstantiationAwareBeanPostProcessor 的子类,因此在这里也会被执行,代码如下:

@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
        // 依次执行所有InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法
        Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
        if (result != null) {
            return result;
        }
    }
    return null;
}

接下来我们来一起看一下在 AnnotationAwareAspectJAutoProxyCreator 的 postProcessBeforeInstantiation() 中做了什么,以下是 AnnotationAwareAspectJAutoProxyCreator 的父类 AbstractAutoProxyCreator 中的 postProcessBeforeInstantiation() 方法

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    // 根据是否factoryBean(&)返回用来缓存的Bean key
    Object cacheKey = getCacheKey(beanClass, beanName);

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

这里的 shouldSkip() 方法的主要目的是:

  1. 获取所有bean的定义名称
  2. 遍历这些bean,找到被@Aspect标注的bean
  3. 通过 MetadataAwareAspectInstanceFactory 获取该bean定义中所有的 Advisor (InstantiationModelAwarePointcutAdvisorImpl )
  4. 最后将扫描到的增强放入缓存 advisorsCache
    1. advisorsCache 处于 AnnotationAwareAspectJAutoProxyCreator 的 aspectJAdvisorsBuilder 中,aspectJAdvisorsBuilder 是一个 BeanFactoryAspectJAdvisorsBuilder类型的属性。
    2. advisorsCache 是一个key为beanName,value为 List< Advisor > 的 ConcurrentHashMap,我们在这里构建的增强类型为 InstantiationModelAwarePointcutAdvisorImpl (Advisor 的子类),内部包含了方法名称,声明类型等细节

经过这个过程,就能获取到我们配置的那些增强,从而在后面的过程中创建代理。

applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)

该方法在这个处理过程中直接返回,略。

@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)

AbstractAutoProxyCreator 中的 postProcessAfterInitialization() 方法内容如下

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // 构建代理key
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

可以看到代码的最后一步调用了 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;
    }
    // 如果获取到增强就创建代理
    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;
}

跳过前半部分的判断,我们来看一下后面的这个通知获取及代理的创建过程:

getAdvicesAndAdvisorsForBean() —— 获取当前bean的增强器
// AbstractAdvisorAutoProxyCreator 的 getAdvicesAndAdvisorsForBean() 方法
protected Object[] getAdvicesAndAdvisorsForBean() 方法(
      Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
	// 获取可以被当前bean使用的增强
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

可以看到 getAdvicesAndAdvisorsForBean() 方法主要是调用了 AbstractAdvisorAutoProxyCreator 的 findEligibleAdvisors() 用来获取针对当前bean的增强,方法如下:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取可用增强,前面已经在resolveBeforeInstantiation()环节存到了缓存中,因此这里直接从缓存中获取
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 寻找哪些增强可以应用到当前bean上
    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);

    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            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);
}

由代码可见,通过createProxy() 构建代理ProxyFactory,并通过ProxyFactory构建代理:

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.");
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

从代码中我们可以知道:

  1. 如果指定了@EnableAspectJAutoProxy的proxyTargetClass = true,则默认使用cglib代理
  2. 如果是默认值(false),则在bean是接口实现的情况下选择jdk代理,否则使用cglib代理

创建代理对象后做了什么?

前面我们知道:创建代理对象后,代理对象保存在容器中。且这个对象里保存了详细的新的,如增强器,目标对象等:

在这里插入图片描述

接下来我们以JDK代理对象为例,通过测试方法调用,一起来看看被代理的方法是如何执行的。

当我们的测试方法被执行时,我们往被执行的方法处打一个断点,并从断点位置进去:

@Test
public void test01() {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestAspectConfig.class);
    TestService bean = applicationContext.getBean(TestService.class);
    bean.add(1,2);// 断点
}

add()方法是我们的代理对象TestService被增强的方法,当调用这个方法时,其实会调用代理对象的invoke()方法,代码如下:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;

    TargetSource targetSource = this.advised.targetSource;
    Object target = null;

    try {
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            return equals(args[0]);
        }
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            return hashCode();
        }
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                 method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;

        if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);
		// 获取拦截器链
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		// 链为空
        if (chain.isEmpty()) {
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            // 直接执行方法
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        } else {
            // 创建 MethodInvocation 方法
            MethodInvocation invocation =
                new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // 调用 MethodInvocation 的 proceed() 方法
            retVal = invocation.proceed();
        }

        Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target &&
            returnType != Object.class && returnType.isInstance(proxy) &&
            !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            retVal = proxy;
        }
        else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException(
                "Null return value from advice does not match primitive return type for: " + method);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

获取拦截器链的过程:

  1. 获取所有的增强

  2. 将增强转换为Interceptor

  3. 将所有增强器转换为List< MethodInterceptor >

  4. 获取到拦截器链之后,传入拦截器链获取方法调用 MethodInvocation

  5. 调用方法,效果

    1. 正常执行:前置通知>目标方法>后置通知>返回通知

    2. 出现异常:前置通知>目标方法>后置通知>异常通知

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值