spring aop源码阅读 笔记

80 阅读3分钟

1、准备工作

bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:component-scan base-package="org.spring.aop" />
    <aop:aspectj-autoproxy/>
</beans>

@Component
public class UserServiceImpl implements UserService{

    public void createa() {
       System.out.println("userServiceImpl a");
    }
}

@Aspect
@Component
public class AnnotationAop {
    @Before("execution(* org.spring.aop.UserServiceImpl.*(..))")
    public void before() {
       System.out.println("---- 发法执行前-----");
    }

    @After("execution(* org.spring.aop.UserServiceImpl.*(..))")
    public void after() {
       System.out.println("---- 发法执行后-----");
    }
    
    ---- 发法执行前-----
    userServiceImpl a
    ---- 发法执行后-----

我们知道,aspectj静态织入,aspectJ在进行aop时,是在编译时就植入代码到class文件,而spring是通过动态代理实现aop,spring是如何利用aspectj做动态代理的呢?

2、流程分析

先来查看xml中aop:aspectj-autoproxy的作用

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
在refresh()方法中初步扫描bean定义,并且返回bean工厂

AopConfigUtils类

public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
       "org.springframework.aop.config.internalAutoProxyCreator";
       
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
       Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
       BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
       if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
          int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
          int requiredPriority = findPriorityForClass(cls);
          if (currentPriority < requiredPriority) {
             apcDefinition.setBeanClassName(cls.getName());
          }
       }
       return null;
    }

    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}
至此,aop:aspectj-autoproxy是为了在bean工厂中添加beanName为internalAutoProxyCreator的bean定义,class org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator的继承关系图

image.png

该类实现了BeanPostProcessor、InstantiationAwareBeanPostProcessor接口,我们知道BeanPostProcessor、InstantiationAwareBeanPostProcessor接口的方法都是对spring bean对象的扩展

首先看InstantiationAwareBeanPostProcessor接口方法的执行

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
       // advisedBean集合中包括不需要的aop代理的bean,比如是aspect切面类或者普通类
       if (this.advisedBeans.containsKey(cacheKey)) {
          return null;
       }
       // isInfrastructureClass(beanClass) 是否是Advice、Pointcut等接口的实现类
       // shouldSkip(beanClass, beanName) 封装所有的before、around等注解封装为Advisor对象
       if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
          this.advisedBeans.put(cacheKey, Boolean.FALSE);
          return null;
       }
    }
    // Create proxy here if we have a custom TargetSource.
    // Suppresses unnecessary default instantiation of the target bean:
    // The TargetSource will handle target instances in a custom fashion.
    // 如果是自定义TargetSource,创建代理
    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;
}
// 在进行aop代理之前,会先获取到所有的Advisor,不仅是实现了Advisor接口,还包括Aspject的before、around注解等也会封装为Advisor备用
// 到此也基本得知,spring利用了aspectj的注解来实现动态代理,只是利用了注解,并未利用其静态织入功能

BeanPostProcessor postProcessAfterInitialization接口的实现(创建aop代理类)

为什么是后置处理来实现aop代理对象的创建?个人理解,如果使用前置处理来创建代理对象不太符合bean生命周期的全流程规范,一个原始bean尚未创建完成就对其进行了代理

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

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
       return bean;
    }
    // 如果目标类是一个切面类,不能进行aop代理,返回原始bean
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
       return bean;
    }
    // 如果目标类是一个切面类,不能进行aop代理,返回原始bean
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
       this.advisedBeans.put(cacheKey, Boolean.FALSE);
       return bean;
    }

    // 获取所有模板类的通知advice
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
       this.advisedBeans.put(cacheKey, Boolean.TRUE);
       // 创建代理对象
       Object proxy = createProxy(
             bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
       this.proxyTypes.put(cacheKey, proxy.getClass());
       return proxy;
    }

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

// jdk动态代理和cglib动态代理的选择
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    // isOptimize设置为true
    // config.isProxyTargetClass() proxyTargetClass为true
    // hasNoUserSuppliedProxyInterfaces(config) 没有指定代理接口
    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.");
       }
       // 目标类是接口 或者  要代理的类是代理类
       if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
          return new JdkDynamicAopProxy(config);
       }
       return new ObjenesisCglibAopProxy(config);
    }
    else {
       return new JdkDynamicAopProxy(config);
    }
}

总结

spring利用的只是aspectj的注解,生成Advisor,再通过bean的后置处理创建bean的代理对象。

spring在jdk动态代理和cglib动态代理的选择中,会根据条件优先选择使用jdk动态代理。