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动态代理源码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Validator接口校验与全局异常处理器

    Spring Validator接口校验与全局异常处理器

    这篇文章主要介绍了Spring Validator接口校验与全局异常处理器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • struts2中simple主题下<s:fieldError>标签默认样式的移除方法

    struts2中simple主题下<s:fieldError>标签默认样式的移除方法

    这篇文章主要给大家介绍了关于struts2中simple主题下<s:fieldError>标签默认样式的移除方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-10-10
  • SpringBoot深入分析讲解监听器模式上

    SpringBoot深入分析讲解监听器模式上

    监听器模式,大家应该并不陌生,主要的组成要素包括了事件、监听器以及广播器;当事件发生时,广播器负责将事件传递给所有已知的监听器,而监听器会对自己感兴趣的事件进行处理
    2022-07-07
  • Java classloader和namespace详细介绍

    Java classloader和namespace详细介绍

    这篇文章主要介绍了Java classloader和namespace详细介绍的相关资料,需要的朋友可以参考下
    2017-03-03
  • Java一致性Hash算法的实现详解

    Java一致性Hash算法的实现详解

    这篇文章主要介绍了Java一致性Hash算法的实现详解,hash的意思是散列,目的将一组输入的数据均匀的分开、打散,往往用来配合路由算法做负载均衡,多用在分布式系统中,需要的朋友可以参考下
    2024-01-01
  • Spring使用aop切面编程时要给那些类加注解的实例

    Spring使用aop切面编程时要给那些类加注解的实例

    在使用切面编程时,通常需要为以下类或组件添加注解来标识它们,以便 Spring 或其他切面框架能够正确识别和处理它们,这篇文章主要介绍了Spring使用aop切面编程时要给那些类加注解,需要的朋友可以参考下
    2023-11-11
  • 使用Lombok时@JsonIgnore注解失效解决方案

    使用Lombok时@JsonIgnore注解失效解决方案

    这篇文章主要为大家介绍了使用Lombok时@JsonIgnore注解失效问题解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • Jmeter访问需要登录的接口如何处理问题

    Jmeter访问需要登录的接口如何处理问题

    这篇文章主要介绍了Jmeter访问需要登录的接口如何处理问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • MyBatis Plus之实现动态排序方式

    MyBatis Plus之实现动态排序方式

    这篇文章主要介绍了MyBatis Plus之实现动态排序方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • java排序算法之_选择排序(实例讲解)

    java排序算法之_选择排序(实例讲解)

    下面小编就为大家带来一篇java排序算法之_选择排序(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09

最新评论