Spring源码系列(九)——AOP动态代理源码分析

AOP的原理实现和Mybatis整合进Spring中的原理实现一模一样,下面来具体分析一下。在看这篇之前,建议先看下上一篇。

Spring源码系列(八)——Mybatis是如何整合进Spring源码分析

https://blog.csdn.net/zxd1435513775/article/details/121180974

一、Spring启动流程再分析

配置类,开启AOP的注解@EnableAspectJAutoProxy

@Configuration
@ComponentScan("com.scorpios")
@EnableAspectJAutoProxy
public class AppConfig {
 
}

切面类

@Aspect
@Component
public class AspectJScorpios {

    @Pointcut("execution(* com.scorpios.service..*.*(..))")
    public void pointCut(){

    }

    @Before("pointCut()")
    public void before(){
        System.out.println(" proxy before ... ");
    }
}

启动类

public static void main( String[] args )
{
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
    ac.register(AppConfig.class);
    ac.refresh();
    XService xService = (XService) ac.getBean("XService");
    xService.print();
}

1. 处理Import过程

对于Import的处理过程,可以看一下源码分析第四篇,包扫描中处理@Import注解部分。

Spring源码系列(四)——ConfigurationClassPostProcessor功能解析

https://blog.csdn.net/zxd1435513775/article/details/120935494

@EnableAspectJAutoProxy注解源码,使用@Import注解,向Spring容器中导入AspectJAutoProxyRegistrar类,而AspectJAutoProxyRegistrar类实现ImportBeanDefinitionRegistrar接口。

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

	boolean proxyTargetClass() default false;
    
	boolean exposeProxy() default false;
    
}

关于@Import注解导入ImportBeanDefinitionRegistrar实现类的介绍可以看一下Spring源码系列(八)

AOP的原理和Mybatis的原理一样,都是通过实现ImportBeanDefinitionRegistrar接口,Mybatis的实现类是MapperScannerRegistrar,而AOP的实现类是AspectJAutoProxyRegistrar

// Mybatis

class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar

// AOP

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar

2. 执行Import导入类

parser.parse(candidates);这行代码里完成了对@Import注解的导入工作,并对实现ImportBeanDefinitionRegistrar接口的类完成了实例化,并把已经创建好的实列放到了ConfigurationClass类的属性importBeanDefinitionRegistrars中,可以看下面断点图。

Spring源码系列(九)——AOP动态代理源码分析

this.reader.loadBeanDefinitions()这个方法中完成了对ImportBeanDefinitionRegistrar接口方法的调用。

下面就来看一下AspectJAutoProxyRegistrar类中实现ImportBeanDefinitionRegistrar接口的方法了。AOP的入口就在这里!!!!

二、AOP源码分析

1. AspectJAutoProxyRegistrar类

来看一下AspectJAutoProxyRegistrar类中实现ImportBeanDefinitionRegistrar接口方法。

该方法的作用就是往Spring容器中添加一个BeanDefinitionbeanNameorg.springframework.aop.config.internalAutoProxyCreatorbeanClassAnnotationAwareAspectJAutoProxyCreator.class

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    @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);
            }
        }
    }
}

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


public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    BeanDefinitionRegistry registry, @Nullable Object source) {

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


private static BeanDefinition registerOrEscalateApcAsRequired(
    Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

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

    // 此处的的beanClass为AnnotationAwareAspectJAutoProxyCreator.class
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 往beanDefinitionMap中注册一个beanName为org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

Spring源码系列(九)——AOP动态代理源码分析

Spring源码系列(九)——AOP动态代理源码分析

2. internalAutoProxyCreator类

再观察一下internalAutoProxyCreator,它的实现类是org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

Spring源码系列(九)——AOP动态代理源码分析

经过refresh()方法中的registerBeanPostProcessors()方法,BeanPostProcessor就已经实例化了,并且添加到了beanFactory工厂中的beanPostProcessors属性中。

Spring源码系列(九)——AOP动态代理源码分析
Spring源码系列(九)——AOP动态代理源码分析

3. BeanPostProcessor方法执行

我们要来看一下BeanPostProcessor的执行时机,在populateBean()属性赋值之后的initializeBean()方法中,进行了Bean后置处理器方法的调用。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    // 权限检查
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    } else {
        // 执行setBeanName/setBeanFactory赋值
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 调用BeanPostProcessor接口中的postProcessBeforeInitialization()方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 执行自定义的init-method方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable ex) {
       // 抛异常代码略
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 调用BeanPostProcessor接口中的postProcessAfterInitialization()方法
        // AOP代理就在AnnotationAwareAspectJAutoProxyCreator类此方法中
        // AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator实现了此方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

上面这个AnnotationAwareAspectJAutoProxyCreator类中的postProcessAfterInitialization()方法执行过后,XService实例就变成了Cglib代理对象了。

Spring源码系列(九)——AOP动态代理源码分析

下面来分析下源码:

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;
    }
    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;
}
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 = 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);
    }

    return proxyFactory.getProxy(getProxyClassLoader());
}


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

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    // 这个判断很重要,可以通过配置文件进行配置,来决定采用什么动态代理
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
			// 抛异常略
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            // 创建JDK动态代理
            return new JdkDynamicAopProxy(config);
        }
        // 创建Cglib动态代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

三、小结

AOP的原理和Mybatis的原理一样,都是利用了Spring@Import导入ImportBeanDefinitionRegistrar这个扩展点。先往容器中添加一个BeanDefinition,然后再适当的时机进行方法的调用。

两篇文章可以对比着看。

上一篇:AOP实现日志打印


下一篇:Spring一套全通3—AOP编程