Spring中的AOP动态代理源码详解

 更新时间:2023年09月18日 10:58:42   作者:止步前行  
这篇文章主要介绍了Spring中的AOP动态代理源码详解,AOP即面向切面编程也称面向方面编程,它是面向对象编程OOP的一种补充,目前已成为一种比较成熟的编程方式,本文就其源码进行解析,需要的朋友可以参考下

一、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 注解部分。

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

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 中,可以看下面断点图。

在这里插入图片描述

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

下面就来看一下 AspectJAutoProxyRegistrar 类中实现 ImportBeanDefinitionRegistrar 接口的方法了。

AOP 的入口就在这里!!!!

二、AOP源码分析

1. AspectJAutoProxyRegistrar类

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

该方法的作用就是往 Spring 容器中添加一个 BeanDefinition , beanName 为 org.springframework.aop.config.internalAutoProxyCreator 。

beanClass 为 AnnotationAwareAspectJAutoProxyCreator.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;
}

在这里插入图片描述

在这里插入图片描述

2. internalAutoProxyCreator类

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

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

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 代理对象了。

在这里插入图片描述

下面来分析下源码:

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,然后再适当的时机进行方法的调用。

到此这篇关于Spring中的AOP动态代理源码详解的文章就介绍到这了,更多相关AOP动态代理源码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用IDEA对SpringBoot应用进行远程调试方式

    使用IDEA对SpringBoot应用进行远程调试方式

    文章介绍了如何在IDEA中对部署在服务器上的SpringBoot应用进行远程调试,通过配置远程调试端口和启动参数,本地IDEA可以设置断点并进行调试
    2025-02-02
  • java json 省市级联实例代码

    java json 省市级联实例代码

    这篇文章介绍了java json 省市级联实例代码,有需要的朋友可以参考一下
    2013-09-09
  • SwiftUI中级List如何添加新内容(2020年教程)

    SwiftUI中级List如何添加新内容(2020年教程)

    这篇文章主要介绍了SwiftUI中级List如何添加新内容,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • spring+hibernate 两种整合方式配置文件的方法

    spring+hibernate 两种整合方式配置文件的方法

    本篇文章主要介绍了spring+hibernate 两种整合方式配置文件的方法,主要有两种方式 1、注解方式 2、xml方式实现,有兴趣的可以了解一下。
    2017-04-04
  • SpringBoot核心@SpringBootApplication使用介绍

    SpringBoot核心@SpringBootApplication使用介绍

    这篇文章主要介绍了SpringBoot核心@SpringBootApplication的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • java程序员如何编写更好的单元测试的7个技巧

    java程序员如何编写更好的单元测试的7个技巧

    测试是开发的一个非常重要的方面,可以在很大程度上决定一个应用程序的命运。良好的测试可以在早期捕获导致应用程序崩溃的问题,但较差的测试往往总是导致故障和停机。本文主要介绍java程序员编写更好的单元测试的7个技巧。下面跟着小编一起来看下吧
    2017-03-03
  • Java实现自定义中文排序的方法机注意事项

    Java实现自定义中文排序的方法机注意事项

    在Java中,中文排序通常涉及到使用Collator类来处理字符串的比较,确保根据汉字的拼音顺序进行排序,本文给大家介绍了Java实现自定义中文排序的方法机注意事项,并有相关的代码示例供大家参考,需要的朋友可以参考下
    2024-10-10
  • Java利用for循环输出空心菱形的实例代码

    Java利用for循环输出空心菱形的实例代码

    这篇文章主要介绍了Java利用for循环输出空心菱形的实例代码,需要的朋友可以参考下
    2014-02-02
  • 深入解析Java中反射中的invoke()方法

    深入解析Java中反射中的invoke()方法

    最近复习了一下Java反射的使用,正好了解一下Java中反射中的invoke()方法,稍微整理精简一下做下分享,感兴趣的可以了解一下
    2021-06-06
  • SpringBoot 指标监控actuator的专题

    SpringBoot 指标监控actuator的专题

    未来每一个微服务在云上部署以后,我们都需要对其进行监控、追踪、审计、控制等。SpringBoot就抽取了Actuator场景,使得我们每个微服务快速引用即可获得生产级别的应用监控、审计等功能,通读本篇对大家的学习或工作具有一定的价值,需要的朋友可以参考下
    2021-11-11

最新评论