SpringAOP源码解析(一)

简单阐述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模式】
          在Spring中很多的 @EnableXXX;
  
  三步:
      1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
      2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
      3)、开启基于注解的aop模式;@EnableAspectJAutoProxy

本篇主要描述了aop的导入流程

@EnableAspectJAutoProxy注解

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

   /**
    * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
    * to standard Java interface-based proxies. The default is {@code false}.
    */
    //proxyTargetClass属性,默认false,尝试采用JDK动态代理织入增强(如果当前类没有实现接口则还是会使用CGLIB);如果设为true,则强制采用CGLIB动态代理织入增强
   boolean proxyTargetClass() default false;

   /**
    * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
    * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
    * Off by default, i.e. no guarantees that {@code AopContext} access will work.
    * @since 4.3.1
    */
    //通过aop框架暴露该代理对象,aopContext能够访问。为了解决类内部方法之间调用时无法增强的问题
   boolean exposeProxy() default false;

}

​ 在这个注解中,通过@Import注解引入AspectJAutoProxyRegistrar.class类。再通过AspectJAutoProxyRegistrar.class类将实现Aop功能的相关类全部导入IOC容器中。

AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		//注册入口类
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		/*
		*  false指用jdk动态代理,
		*  true则开启cglib代理
		* */
		//代理机制
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}

			//是否需要把代理对象暴露出来,简单来说是否要把代理对象用ThreadLocal存起来,如果是true就是需要
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

}

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)AnnotationAwareAspectJAutoProxyCreator.class注册到Ioc容器中,并且beanName取为org.springframework.aop.config.internalAutoProxyCreator,注册代码具体代码在AopConfigUtils.java registerOrEscalateApcAsRequired方法中,调用过程为

private static BeanDefinition registerOrEscalateApcAsRequired(
      Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    //省略代码
	...

   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
/*
*向Ioc内注册AnnotationAwareAspectJAutoProxyCreator.class              *AUTO_PROXY_CREATOR_BEAN_NAME="org.springframework.aop.config.internalAutoProxyCreator"
**/
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

image-20211020101357736

可以看见,在返回语句执行前,AnnotationAwareAspectJAutoProxyCreator已经注入容器中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值