Spring AOP源码学习:AOP 注解的解析

简介: 上文介绍了AOP 的基本概念,本文开始进入AOP 的源码解析,本文仍以 AspectJ 来进行介绍,首先是 AOP 注解的解析。

前言


上文介绍了AOP的基本概念,本文开始进入AOP 的源码解析,本文仍以 AspectJ 来进行介绍,首先是 AOP 注解的解析。

 

正文


当使用 <aop:aspectj-autoproxy /> 注解开启 AOP 功能时。

Spring会从“META-INF/spring.handlers” 配置文件中拿到该注解对应的 NamespaceHandlerSupportAopNamespaceHandler

image.png

AopNamespaceHandler init 方法会给该注解注册对应的解析器,aspectj-autoproxy 对应的解析器是:AspectJAutoProxyBeanDefinitionParser

@Override
public void init() {
    // In 2.0 XSD as well as in 2.1 XSD.
    registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
    registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
    registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
    // Only in 2.0 XSD: moved to context namespace as of 2.1
    registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}

我们知道,当解析到 <aop:aspectj-autoproxy /> 注解时,会调用AspectJAutoProxyBeanDefinitionParser parse方法。

关于自定义注解的解析内容之前 IoC 的文章介绍过了,如果不了解的可以参考:Spring IoCparseCustomElement 详解

 

AspectJAutoProxyBeanDefinitionParser#parse


@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    // 1.注册AspectJAnnotationAutoProxyCreator
    AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
    // 2.对于注解中子节点的处理
    extendBeanDefinition(element, parserContext);
    return null;
}

1.注册 AspectJAnnotationAutoProxyCreator,见代码块1

 

代码块1AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        ParserContext parserContext, Element sourceElement) {
    // 1.注册AspectJAnnotationAutoProxyCreator
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    // 2.对于proxy-target-class以及expose-proxy属性的处理
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    // 3.注册组件并通知,便于监听器做进一步处理
    registerComponentIfNecessary(beanDefinition, parserContext);
}

1.注册 AspectJAnnotationAutoProxyCreator,见代码块2

2.对于 proxy-target-class 以及 expose-proxy 属性的处理,见代码块3

 

代码块2AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    // 1.如果注册表中已经存在beanName=org.springframework.aop.config.internalAutoProxyCreator的bean,则按优先级进行选择。
    // beanName=org.springframework.aop.config.internalAutoProxyCreator,可能存在的beanClass有三种,按优先级排序如下:
    // InfrastructureAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        // 拿到已经存在的bean定义
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // 如果已经存在的bean的className与当前要注册的bean的className不相同,则按优先级进行选择
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            // 拿到已经存在的bean的优先级
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            // 拿到当前要注册的bean的优先级
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                // 如果当前要注册的bean的优先级大于已经存在的bean的优先级,则将bean的className替换为当前要注册的bean的className,
                apcDefinition.setBeanClassName(cls.getName());
            }
            // 如果小于,则不做处理
        }
        // 如果已经存在的bean的className与当前要注册的bean的className相同,则无需进行任何处理
        return null;
    }
    // 2.如果注册表中还不存在,则新建一个Bean定义,并添加到注册表中
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    // 设置了order为最高优先级
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 注册BeanDefinition,beanName为org.springframework.aop.config.internalAutoProxyCreator
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

org.springframework.aop.config.internalAutoProxyCreator 是内部管理的自动代理创建者的 bean 名称,可能对应的 beanClassName 有三种,对应的注解如下:


InfrastructureAdvisorAutoProxyCreator<tx:annotation-driven />

AspectJAwareAdvisorAutoProxyCreator<aop:config />

AnnotationAwareAspectJAutoProxyCreator<aop:aspectj-autoproxy />


当同时存在多个注解时,会使用优先级最高的 beanClassName 来作为 org.springframework.aop.config.internalAutoProxyCreator beanClassName。本系列文章暂不考虑同时存在其他注解的情况,所以在这边会注册的 beanClassName 为:AnnotationAwareAspectJAutoProxyCreator

 

代码块3useClassProxyingIfNecessary

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
    if (sourceElement != null) {
        boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
        if (proxyTargetClass) {
            // 如果节点设置了proxy-target-class=true,则给beanName为org.springframework.aop.config.internalAutoProxyCreator
            // 的BeanDefinition添加proxyTargetClass=true的属性,之后创建代理的时候将强制使用Cglib代理
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
        if (exposeProxy) {
            // 如果节点设置了expose-proxy=true,则给beanName为org.springframework.aop.config.internalAutoProxyCreator
            // 的BeanDefinition添加exposeProxy=true的属性,之后创建拦截器时会根据该属性选择是否暴露代理类
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}

 

总结


本文的内容比较简单,最重要的内容就是注册了内部管理的自动代理创建者的 beanAnnotationAwareAspectJAutoProxyCreatorAOP 的大部分重要内容都在这个bean 里,之后会一一介绍。

 

相关文章


Spring AOP:基本概念

相关文章
|
2月前
|
缓存 安全 Java
Spring Security通用权限管理模型解析
Spring Security作为Spring生态的核心安全框架,结合RBAC与ACL权限模型,基于IoC与AOP构建灵活、可扩展的企业级权限控制体系,涵盖认证、授权流程及数据库设计、性能优化等实现策略。
191 0
|
2月前
|
缓存 安全 Java
Spring Security权限管理解析
Spring Security是Spring生态中的核心安全框架,采用认证与授权分离架构,提供高度可定制的权限管理方案。其基于过滤器链实现认证流程,通过SecurityContextHolder管理用户状态,并结合RBAC模型与动态权限决策,支持细粒度访问控制。通过扩展点如自定义投票器、注解式校验与前端标签,可灵活适配多租户、API网关等复杂场景。结合缓存优化与无状态设计,适用于高并发与前后端分离架构。
203 0
|
2月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
431 128
|
2月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
|
21天前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
21天前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
30天前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
262 2
|
2月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
244 12
|
2月前
|
Java 数据库 数据安全/隐私保护
Spring Boot四层架构深度解析
本文详解Spring Boot四层架构(Controller-Service-DAO-Database)的核心思想与实战应用,涵盖职责划分、代码结构、依赖注入、事务管理及常见问题解决方案,助力构建高内聚、低耦合的企业级应用。
630 1
|
2月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
143 0
探索Spring Boot的@Conditional注解的上下文配置

热门文章

最新文章

推荐镜像

更多
  • DNS