爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      Spring的AOP原理分析

      首页 知识中心 软件开发 文章详情页

      Spring的AOP原理分析

      2023-07-04 07:11:19 阅读次数:80

      java,spring

      AOP原理

      1.AOP功能测试

      AOP:【动态代理】

      ​ 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;

      测试步骤:

      ​ 1、导入aop模块;Spring AOP:(spring-aspects)

      ​ 2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)

      ​ 3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;

      通知方法:

      • 前置通知(@Before):logStart:在目标方法(div)运行之前运行

      • 后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)

      • 返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行

      • 异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行

      • 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())

      4、给切面类的目标方法标注何时何地运行(通知注解);

      5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;

      6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)

      [7]、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】

      目标类MathCalculator:

      public class MathCalculator {
         //目标方法(待增强方法)
         public int div(int i,int j){
            System.out.println("MathCalculator...div...");
            return i/j;    
         }
      }
      

      切面类:

      /**
       * 切面类
       * @Aspect:告诉Spring这是一个切面类
       */
      @Aspect
      public class LogAspects {
          //抽取公共的切入点表达式
          //1.本类引用
          //2.其他的切面引用
          @Pointcut("execution(public int com.rg.aop.MathCalculator.*(..))")
          public void pointCut(){}
      
          //在目标方法之前切入:切入表达式(指定那个方法切入)
          @Before("pointCut()")
          public void logStart(JoinPoint joinPoint){
              Object[] args = joinPoint.getArgs();
              System.out.println(joinPoint.getSignature().getName()+"正在运行...@Before:参数列表是:"+ Arrays.asList(args));
          }
      
          //最终通知
          @After("com.rg.aop.LogAspects.pointCut()")
          public void logEnd(JoinPoint joinPoint){
              Object[] args = joinPoint.getArgs();
              System.out.println(joinPoint.getSignature().getName()+"结束...@After:参数列表是:"+Arrays.asList(args));
          }
      
      
          // 后置通知 切入点之后执行.
          @AfterReturning(value = "pointCut()",returning = "result")
          //JointPoint 一定要出现在参数表的第一位.
          public void logRegurning(JoinPoint joinPoint,Object result){
      
              System.out.println(joinPoint.getSignature().getName()+"正常返回...运行结果:"+result);
          }
      
          @AfterThrowing(value = "pointCut()",throwing = "exception")
          public void logException(JoinPoint joinPoint,Exception exception){
              System.out.println(joinPoint.getSignature().getName()+"出现异常...异常信息:"+exception);
          }
      }
      

      配置类:

      @EnableAspectJAutoProxy  //开启基于注解的AOP模式
      @Configuration
      public class MainConfigOfAOP {
          //业务逻辑类加入容器中
          @Bean
          public MathCalculator calculator(){
              return new MathCalculator();
          }
      
          //将切面类加入到容器中
          @Bean
          public LogAspects logAspects(){
              return new LogAspects();
          }
      
      }
      

      测试:

      @Test
      public void test01(){
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
          //在这里MathCalculator对象必须是Spring提供的,因为只有Spring提供的对象才会有动态代理等功能.
          // MathCalculator mathCalculator1 = new MathCalculator();
          // mathCalculator1.div();
          MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
          mathCalculator.div(1,1);
          applicationContext.close();
      }
      

      运行结果:

      Spring的AOP原理分析

      总结:

      • 1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
      • 2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
      • 3)、开启基于注解的aop模式;@EnableAspectJAutoProxy

      2.@EnableAspectJAutoProxy原理(一)—简单分析

      1.分析@EnableAspectJAutoProxy

      @EnableAspectJAutoProxy
      		↓
      导入@Import(AspectJAutoProxyRegistrar.class)
                  ↓
      class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
      	AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
      	//注册一个AspectJAnnotationAutoProxyCreator
      	...
      }
      			↓
                      
      registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);//注册或升级如果需要...
      
      			↓
       if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {//判断是否包含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);//cls就是上面的AnnotationAwareAspectJAutoProxyCreator,创建一个RootBeanDefinition
      //为beanDefinition设置相关属性.
      beanDefinition.setSource(source);
      beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
      beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
      //将其注册到registry中.命名为AUTO_PROXY_CREATOR_BEAN_NAME= internalAutoProxyCreator
      registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
      return beanDefinition;//返回.   
      

      AUTO_PROXY_CREATOR_BEAN_NAME=internalAutoProxyCreator=cls

      =AnnotationAwareAspectJAutoProxyCreator

      分析结果:给容器中注册一个AnnotationAwareAspectJAutoProxyCreator:注解装配模式的AspectJ切面自动代理创建器.

      小技巧:以后如果遇到@EnableXXX 注解.我们就点进去看看,有没有@Inport,其他类,然后一步步的分析,找出这些操作的最终的结果.

      2.AnnotationAwareAspectJAutoProxyCreator的继承体系:

      AnnotationAwareAspectJAutoProxyCreator
      	->AspectJAwareAdvisorAutoProxyCreator
      		->AbstractAdvisorAutoProxyCreator
      			->AbstractAutoProxyCreator
      				implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
          		->ProxyProcessorSupport implements ordered...
          		->...
      

      注意:

      XXXBeanPostProcessor后置处理器(在bean初始化完成前后做事情)

      BeanFactoryAware:自动装配bean到BeanFactory中

      3.@EnableAspectJAutoProxy原理(二)—创建和注册AnnotationAwareAspectJAutoProxyCreator

      AbstractAutoProxyCreator:
      设置BeanFactory:		setBeanFactory(☆)
      后置处理器的方法        postProcessBeforeInstantiation(☆)
              			 postProcessAfterInitialization(☆)
              			 ↓
      AbstractAdvisorAutoProxyCreator
      重写setBeanFactory(),且方法内调用initBeanFactory()(☆)
      					↓
      AspectJAwareAdvisorAutoProxyCreator:没有与之相关的方法
      					↓
      AnnotationAwareAspectJAutoProxyCreator:
      	initBeanFactory()  调用并重写父类的该方法.(☆)
      	
              			 
      

      所以我们可以在上面(标有五角星的方法),以及LogAspects中的两个方法上打断点进行调试:>

      Debug流程分析:

      1)传入配置类,创建IOC容器
      ... = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
      			↓
      2)注册配置类,调用refresh刷新容器
           register(annotatedClasses);
      	 refresh();=>调用registerBeanPostProcessors方法
      3)registerBeanPostProcessors(beanFactory):注册bean的后置处理器,方便拦截.
          1)、 获取IOC容器中已经定义了的需要创建对象的所有BeanPostProcessor       
               String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
      
      		// Register BeanPostProcessorChecker that logs an info message when
      		// a bean is created during BeanPostProcessor instantiation, i.e. when
      		// a bean is not eligible for getting processed by all BeanPostProcessors.
      		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
      	2)、给容器中加入别的BeanPostProcessor
      		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
      		//分离实现了PriorityOrdered,Ordered,rest接口的BeanPostProcessors
      		// Separate between BeanPostProcessors that implement PriorityOrdered,
      		// Ordered, and the rest.
      		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
      		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
      		List<String> orderedPostProcessorNames = new ArrayList<>();
      		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
      		for (String ppName : postProcessorNames) {
      			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
      				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      				priorityOrderedPostProcessors.add(pp);//如果是PriorityOrdered类型,就将其加入到priorityOrderedPostProcessors集合中.下面同理...
      				if (pp instanceof MergedBeanDefinitionPostProcessor) {
      					internalPostProcessors.add(pp);
      				}
      			}
      			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
      				orderedPostProcessorNames.add(ppName);
      			}
      			else {
      				nonOrderedPostProcessorNames.add(ppName);
      			}
      		}
      		//分离完毕
       	3).优先注册实现了PriorityOrdered接口的BeanPostProcessor
      		// First, register the BeanPostProcessors that implement PriorityOrdered.
      		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
      		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
      	4).再给容器中注册实现了Order接口的BeanPostProcessor(咱们关注的internalAutoProxyCreator会进入这里)
      		// Next, register the BeanPostProcessors that implement Ordered.
      		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
      		for (String ppName : orderedPostProcessorNames) {
                  //6.注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存到容器中.
                  // 根据名称注册BeanPostProcessor(此过程很难,后序可以自己debug看每一步.)
      			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      			orderedPostProcessors.add(pp);
      			if (pp instanceof MergedBeanDefinitionPostProcessor) {
      				internalPostProcessors.add(pp);
      			}
      		}
      		sortPostProcessors(orderedPostProcessors, beanFactory);
      	7).把BeanPostProcessor注册到BeanFactory中.底层原理是:beanFactory.addBeanPostProcessor(postProcessor);
      	
      		registerBeanPostProcessors(beanFactory, orderedPostProcessors);
      	5).注册没实现优先级接口的普通BeanPostProcessors
      		// Now, register all regular BeanPostProcessors.
      		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
      		for (String ppName : nonOrderedPostProcessorNames) {
                 
      			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      			nonOrderedPostProcessors.add(pp);
      			if (pp instanceof MergedBeanDefinitionPostProcessor) {
      				internalPostProcessors.add(pp);
      			}
      		}
      		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
      
      		// Finally, re-register all internal BeanPostProcessors.
      		sortPostProcessors(internalPostProcessors, beanFactory);
      
      		registerBeanPostProcessors(beanFactory, internalPostProcessors);
      
      		// Re-register post-processor for detecting inner beans as ApplicationListeners,
      		// moving it to the end of the processor chain (for picking up proxies etc).
      	
      		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));)
      

      ​ 创建和注册AnnotationAwareAspectJAutoProxyCreator的过程小结:

       * 		1)、传入配置类,创建ioc容器
       * 		2)、注册配置类,调用refresh()刷新容器;
       * 		3)、registerBeanPostProcessors(beanFactory);注册bean的后置处理器来方便拦截bean的创建;
       * 			1)、先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
       * 			2)、给容器中加别的BeanPostProcessor
       * 			3)、优先注册实现了PriorityOrdered接口的BeanPostProcessor;
       * 			4)、再给容器中注册实现了Ordered接口的BeanPostProcessor;
       * 			5)、注册没实现优先级接口的BeanPostProcessor;
       * 			6)、注册BeanPostProcessor(实现ordered接口的),实际上就是创建BeanPostProcessor对象,保存在容器中;
       * 				创建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】
       * 				1)、创建Bean的实例
       * 				2)、populateBean;给bean的各种属性赋值
       * 				3)、initializeBean:初始化bean;
       * 						1)、invokeAwareMethods():处理Aware接口的方法回调
       * 						2)、applyBeanPostProcessorsBeforeInitialization():应用后置处理器的postProcessBeforeInitialization()
       * 						3)、invokeInitMethods();执行自定义的初始化方法
       * 						4)、applyBeanPostProcessorsAfterInitialization();执行后置处理器的postProcessAfterInitialization();
       * 				4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;--》aspectJAdvisorsBuilder
       * 			7)、把BeanPostProcessor注册到BeanFactory中;
       * 				beanFactory.addBeanPostProcessor(postProcessor);
       * =======以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程========
      
      

      4.@EnableAspectJAutoProxy原理(三)—finishBeanFactoryInitialization()分析

      registerBeanPostProcessors(beanFactory) ((原理二)已完成)
      			↓↓
      finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;创建剩下的单实例bean
      			↓↓进入
      beanFactory.preInstantiateSingletons();//实例化所有剩余的单例对象。
      			↓↓进入
      1)、遍历获取容器中所有的Bean,依次创建对象:getBean(beanName);
      		getBean->doGetBean()
      		doGetBean()剖析:
      		//先从缓存中获取当前Bean,如果能获取到,则说明bean是之前被创建过的,直接使用,否则再进行创建.
      		Object sharedInstance = getSingleton(beanName);
      		if (sharedInstance != null && args == null) {//
      			...
      			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//使用
      		}else{
      			...
      			sharedInstance = getSingleton(..){
      				return createBean(beanName, mbd, args);//进行创建Bean
      			}
      			...
      		}
      2)createBean(..):创建Bean(同原理(二)3.6)
      // AnnotationAwareAspectJAutoProxyCreator 会在任何bean创建之前先尝试返回bean的代理实例,如果不能则进行创建
      ☆☆☆ Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      		↓↓如果不能返回,执行下面的代码.
      doCreateBean():真正的创建Bean
      		 1) createBeanInstance(beanName, mbd, args);//创建Bean实例
      		 2) populateBean(beanName, mbd, instanceWrapper);//属性赋值
      		 3) initializeBean(beanName, exposedObject, mbd);//初始化Bean
      				1)、invokeAwareMethods():处理Aware接口的方法回调
       * 				2)、applyBeanPostProcessorsBeforeInitialization():应用后置处理器的postProcessBeforeInitialization()
       * 				3)、invokeInitMethods();执行自定义的初始化方法
       * 				4)、applyBeanPostProcessorsAfterInitialization();执行后置处理器的postProcessAfterInitialization();
       * 		4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;
      

      resolveBeforeInstantiation(beanName, mbdToUse);源码解析

      resolveBeforeInstantiation(beanName, mbdToUse);
      		↓↓后置处理器返回代理对象的原理;如果能返回代理对象就使用,如果不能就继续.
      1).bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
      		↓↓进入
      		//拿到所有的后置处理器,如果是InstantiationAwareBeanPostProcessor,就执行postProcessBeforeInstantiation方法.
      		for (BeanPostProcessor bp : getBeanPostProcessors()) {
      			if (bp instanceof InstantiationAwareBeanPostProcessor) {
      				...
      				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
      				if (result != null) {
      					return result;
      				}
      			}
      		}
      
      
      2). if(bean!=null){
              bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
          }//如果不为空,执行postProcessAfterInitialization 
      			↓↓不为空时进入 ,执行postProcessAfterInitialization方法.
      		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      			Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
      			if (current == null) {
      				return result;
      			}
      			result = current;
      		}
      		return result;
      

      注意:

      【BeanPostProcessor是在Bean对象创建完成初始化前后调用的】

      【InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的】

      关于创建Bean:AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前会有一个拦截,InstantiationAwareBeanPostProcessor会调用postProcessBeforeInstantiation().

      小结: finishBeanFactoryInitialization(beanFactory)(续原理二):

      4)、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;创建剩下的单实例bean
       *           1)、遍历获取容器中所有的Bean,依次创建对象getBean(beanName);
       *              getBean->doGetBean()->getSingleton()->
       *           2)、创建bean
       *              【AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前会有一个拦截,InstantiationAwareBeanPostProcessor,会调用postProcessBeforeInstantiation()】
       *              1)、先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;
       *                 只要创建好的Bean都会被缓存起来
       *              2)、createBean();创建bean;
       *                 AnnotationAwareAspectJAutoProxyCreator 会在任何bean创建之前先尝试返回bean的实例
       *                 【BeanPostProcessor是在Bean对象创建完成初始化前后调用的】
       *                 【InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的】
       *                 1)、resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation
       *                    希望后置处理器在此能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续
       *                    1)、后置处理器先尝试返回对象;
       *                       bean = applyBeanPostProcessorsBeforeInstantiation():
       *                          拿到所有后置处理器,如果是InstantiationAwareBeanPostProcessor;
       *                          就执行postProcessBeforeInstantiation
       *                       if (bean != null) {
      bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
      }
       *
       *                 2)、doCreateBean(beanName, mbdToUse, args);真正的去创建一个bean实例;和3.6流程一样;
      

      5.@EnableAspectJAutoProxy原理(四)

      5.1postProcessBeforeInstantiation()源码分析

      
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
      			if (bp instanceof InstantiationAwareBeanPostProcessor) {
      // 1)、每一个bean创建之前,调用postProcessBeforeInstantiation();
      				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
      				if (result != null) {
      					return result;
      				}
      			}
      }
      			↓↓进入调用postProcessBeforeInstantiation();
          if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName))  {			 //1)、判断当前bean是否在advisedBeans中(保存了所有需要增强bean)
      			if (this.advisedBeans.containsKey(cacheKey)) {
      				return null;
      			}
      			//2) ,判断当前Bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean或者是否是切面(@Aspect)
      			//3)是否需要跳过
      			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
      				this.advisedBeans.put(cacheKey, Boolean.FALSE);
      				return null;
      			}
      }
      

      shouldSkip()方法解析:

      //1) 获取候选的增强器(切面里面的通知方法)【List<Advisor> candidateAdvisors】
      List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
      for(Advisor advisor : candidateAdvisors){
      //2) 判断每一个增强器是否是 AspectJPointcutAdvisor 类型的;返回true
      	if(advisor instanceof AspectJPointcutAdvisor){
      		if(((AbstractAspectJAdvice)advisor.getAdvice()).getAspectName().equals(beanName))		{ 
      			return true;
      		}
      	}
      }
      return super.shouldSkip(beanClass,beanName);//否则永远返回false.(底层父类永远返回false)
      

      总结:创建对象之前先执行,postProcessBeforeInstantiation(),之后创建对象—AnnotationAwareAspectJAutoProxyCreator,最后开始执行:postProcessAfterInitialization().

      5.2postProcessAfterInitialization()的底层源码:

      postProcessAfterInitialization().
      	↓↓
      return wrapIfNecessary(bean, beanName, cacheKey);//包装如果需要的情况下.
      	↓↓进入
      1) 获取当前bean的所有增强其(通知方法) Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(...)
      2) 保存当前bean在adviseBeans中;
      3) 如果当前bean需要增强,创建当前bean的代理对象;
      	 1) 获取所有增强器(通知方法)Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
      	 2) 保存到proxyFactory: proxyFactory.addAdvisors(advisors);
      	 3)	创建代理对象:proxyFactory.getProxy(getProxyClassLoader());Spring自己决定创建哪种类型
      	  		JdkDynamicAopProxy(config);jdk动态代理;
                  ObjenesisCglibAopProxy(config);cglib的动态代理;
      4)给容器中返回当前组件使用cglib增强了的代理对象;
      
      所有以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程.
      	 
      

      小结:

      AnnotationAwareAspectJAutoProxyCreator【后置处理类型:InstantiationAwareBeanPostProcessor】
      作用:
       * 1)、每一个bean创建之前,调用postProcessBeforeInstantiation();
       * 		关心MathCalculator和LogAspect的创建
       * 		1)、判断当前bean是否在advisedBeans中(保存了所有需要增强bean)
       * 		2)、判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,
       * 			或者是否是切面(@Aspect)
       * 		3)、是否需要跳过
       * 			1)、获取候选的增强器(切面里面的通知方法)【List<Advisor> candidateAdvisors】
       * 				每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor;
       * 				判断每一个增强器是否是 AspectJPointcutAdvisor 类型的;返回true
       * 			2)、永远返回false
       * 
       * 2)、创建对象
       * 3)调用postProcessAfterInitialization;
       * 		return wrapIfNecessary(bean, beanName, cacheKey);//包装如果需要的情况下
       * 		1)、获取当前bean的所有增强器(通知方法)  Object[]  specificInterceptors
       * 			1、找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)
       * 			2、获取到能在bean使用的增强器。
       * 			3、给增强器排序
       * 		2)、保存当前bean在advisedBeans中;
       * 		3)、如果当前bean需要增强,创建当前bean的代理对象;
       * 			1)、获取所有增强器(通知方法)
       * 			2)、保存到proxyFactory   
       * 			3)、创建代理对象:Spring自动决定
       * 				JdkDynamicAopProxy(config);jdk动态代理;
       * 				ObjenesisCglibAopProxy(config);cglib的动态代理;
       * 		4)、给容器中返回当前组件使用cglib增强了的代理对象;
       * 		5)、以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;
      

      6.@EnableAspectAutoProxy原理(五)—目标方法执行

      *   3)、目标方法执行  ;
      *     容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx);
      *     1)、CglibAopProxy.intercept();拦截目标方法的执行
      *     2)、根据ProxyFactory对象获取将要执行的目标方法拦截器链;
      *        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      *        1)、List<Object> interceptorList保存所有拦截器 5
      *           一个默认的ExposeInvocationInterceptor 和 4个增强器;
      *        2)、遍历所有的增强器,将其转为Interceptor;
      *           registry.getInterceptors(advisor);   ↓↓ 
      *        3).将增强器转为List<MethodInterceptor>;
      *           如果是MethodInterceptor,直接加入到集合中
      *           如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
      *           转换完成返回MethodInterceptor数组;
      *
      *     3)、如果没有拦截器链,直接执行目标方法;
      *        拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
      *     4)、如果有拦截器链,把需要执行的目标对象,目标方法,
      *        拦截器链等信息传入创建一个 CglibMethodInvocation 对象,
      *        并调用 Object retVal =  mi.proceed();
      
      

      7.@EnableAspectAutoProxy原理(六)—拦截器链的触发过程

      步骤图解:
      Spring的AOP原理分析

      *    拦截器链的触发过程;
      *     1)、如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(执行到了最后一个拦截器)执行目标方法;
      *     2)、链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;
      *     拦截器链的机制,保证通知方法与目标方法的执行顺序;
      

      AOP原理总结:

      *   总结:
      *     1)、  @EnableAspectJAutoProxy 开启AOP功能
      *     2)、 @EnableAspectJAutoProxy 会给容器中注册一个组件 		     	
                          AnnotationAwareAspectJAutoProxyCreator(是一个后置处理器;)
      *     3)、容器的创建流程:
      *        1)、registerBeanPostProcessors()注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象
      *        2)、finishBeanFactoryInitialization()初始化剩下的单实例bean
      *           1)、创建业务逻辑组件和切面组件
      *           2)、AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程
      *           3)、组件创建完之后,判断组件是否需要增强
      *              是:切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib);
      *     4)、执行目标方法:
      *        1)、代理对象执行目标方法
      *        2)、CglibAopProxy.intercept();
      *           1)、得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
      *           2)、利用拦截器的链式机制,依次进入每一个拦截器进行执行;
      *           3)、效果:
      *              正常执行:前置通知-》目标方法-》后置通知-》返回通知
      *              出现异常:前置通知-》目标方法-》后置通知-》异常通知
      */
      中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx);
      *     1)、CglibAopProxy.intercept();拦截目标方法的执行
      *     2)、根据ProxyFactory对象获取将要执行的目标方法拦截器链;
      *        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      *        1)、List<Object> interceptorList保存所有拦截器 5
      *           一个默认的ExposeInvocationInterceptor 和 4个增强器;
      *        2)、遍历所有的增强器,将其转为Interceptor;
      *           registry.getInterceptors(advisor);   ↓↓ 
      *        3).将增强器转为List<MethodInterceptor>;
      *           如果是MethodInterceptor,直接加入到集合中
      *           如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
      *           转换完成返回MethodInterceptor数组;
      *
      *     3)、如果没有拦截器链,直接执行目标方法;
      *        拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
      *     4)、如果有拦截器链,把需要执行的目标对象,目标方法,
      *        拦截器链等信息传入创建一个 CglibMethodInvocation 对象,
      *        并调用 Object retVal =  mi.proceed();
      
      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/LXYDSF/article/details/120162068,作者:爱编程的大李子,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:Spring IOC 源码分析之深入理解 IOC

      下一篇:Python 实现专属字典生成器

      相关文章

      2025-05-16 09:15:10

      52.介绍AOP有几种实现方式

      52.介绍AOP有几种实现方式

      2025-05-16 09:15:10
      gt , lt , Spring
      2025-05-14 10:02:58

      java休眠到指定时间怎么写

      java休眠到指定时间怎么写

      2025-05-14 10:02:58
      java , sleep , Thread , util , 方法
      2025-05-14 10:02:58

      java项目多端数据同步解决方案

      多端数据同步是指在多个设备(例如桌面应用、移动应用、Web应用)之间保持数据的一致性。

      2025-05-14 10:02:58
      java , Spring , WebSocket , 同步 , 数据 , 版本号
      2025-05-13 09:49:12

      Java学习(动态代理的思想详细分析与案例准备)(1)

      Java学习(动态代理的思想详细分析与案例准备)(1)

      2025-05-13 09:49:12
      java , 代理 , 代码 , 对象 , 接口 , 方法 , 需要
      2025-05-09 08:20:32

      基于IDEA的Maven简单工程创建及结构分析

      通过一个 mvn 命令直接让我们创建一个 Maven 的脚手架。

      2025-05-09 08:20:32
      java , Maven , xml , 创建 , 文件 , 文件夹 , 项目
      2025-05-08 09:03:57

      前K个高频元素java

      给定一个非空的整数数组,返回其中出现频率前 前K个高频元素java 高的元素。

      2025-05-08 09:03:57
      java , 元素 , 样例 , 给定
      2025-05-08 09:03:21

      基于java Swing开发的学生成绩管理系统【项目源码+数据库脚本】

      基于java Swing开发的学生成绩管理系统【项目源码+数据库脚本】

      2025-05-08 09:03:21
      java , Swing , 学生 , 源码
      2025-05-08 09:03:21

      基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】

      本项目是一套基于spring+jsp+mysql实现的Java web论坛系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。

      2025-05-08 09:03:21
      Java , jsp , spring , 功能 , 源码
      2025-05-08 09:03:21

      java Swing学生成绩管理系统【项目源码+数据库脚本】

      本项目是一套基于java Swing开发的学生成绩管理系统,主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。

      2025-05-08 09:03:21
      java , 学生 , 成绩 , 数据库 , 源码
      2025-05-08 09:03:07

      spring Bean的作用域和生命周期

      spring Bean的作用域和生命周期

      2025-05-08 09:03:07
      Bean , method , spring , 作用域 , 配置文件
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5242479

      查看更多

      最新文章

      52.介绍AOP有几种实现方式

      2025-05-16 09:15:10

      java项目多端数据同步解决方案

      2025-05-14 10:02:58

      Java学习(动态代理的思想详细分析与案例准备)(1)

      2025-05-13 09:49:12

      前K个高频元素java

      2025-05-08 09:03:57

      基于java Swing开发的学生成绩管理系统【项目源码+数据库脚本】

      2025-05-08 09:03:21

      基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】

      2025-05-08 09:03:21

      查看更多

      热门文章

      JAVA__接口的作用

      2023-04-18 14:14:13

      Java学习之算术运算符两只老虎

      2023-04-19 09:23:13

      排序算法Java版-归并排序算法

      2023-04-24 11:25:19

      JAVA多线程学习笔记

      2023-05-11 06:05:48

      try...catch...finally java

      2023-03-29 09:40:26

      Java:apache.poi读写Excel文件

      2023-02-22 06:40:54

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      springmvc注解的使用

      Spring系列之零碎知识点

      设计信息录入界面,完成人员基本信息的录入工作

      java读取与写入excel(.xls .xlsx)

      Java学习路线-10:异常

      StackOverflow网友Bert F发帖提问:哪本最具影响力的书,是每个程序员都应该读的?...

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号