Spring源码分析之AOP

Spring AOP源码分析 1. 什么是AOP 与OOP对比,AOP是处理一些横切性问题,这些横切性问题不会影响到主逻辑实现的,但是会散落到代码的各个部分,难以维护。 AOP就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。 2. AOP的应用场景 日志记录 权限验证 效率检查 事务管理 3. Spring AOP原理及其应用 3.1 AOP相关概念 Aspect(切面): 通常是一个类(交给Spring... 阅读详情

AOP是什么

面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计剖面导向程序设计),是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进行进一步分离,以提高程序代码的模块化程度。通过在现有代码基础上增加额外的通知(Advice)机制,能够对被声明为“切点(Pointcut)”的代码块进行统一管理与装饰。

怎么在Spring里使用AOP

Spring里,AOP通过EnableAspectJAutoProxy注解开启。默认情况下,Spring会通过AopAutoConfiguration自动引入这个注解

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
   
   

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {
   
   

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
		static class JdkDynamicAutoProxyConfiguration {
   
   

		}

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		static class CglibAutoProxyConfiguration {
   
   

		}

	}
}

可以看到,如果我们不主动设置spring.aop.auto=false。那么Spring默认会启用AOP。接下来,我们可以通过在类上标注Aspect即可使用AOP

package org.example.aspect;

@Aspect
@Component
public class SampleAspect {
   
   

    @Pointcut("execution(* org.example.xxx.*.*(..))")
    private void executionPointcut() {
   
   

    }

    @After(value = "executionPointcut()")
    public void doAfter() {
   
   
        
    }
}

源码分析

1. AOP初始化

1.1 初始化AspectJAutoProxyRegistrar

EnableAspectJAutoProxy通过Import注解引入了AspectJAutoProxyRegistrar

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
   
   
}

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrarSpring在初始化AopAutoConfiguration时把所有通过Import注解引入的ImportBeanDefinitionRegistrar实现类拿出来进行初始化,并调用其registerBeanDefinitions函数

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
   
   

	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   
   

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

}

1.2 初始化AnnotationAwareAspectJAutoProxyCreator

AspectJAutoProxyRegistrar 则在registerBeanDefinitions注册了一个AnnotationAwareAspectJAutoProxyCreatorBeanDefinition

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
   
   

		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessorSpring会在初始化普通Bean之前初始化所有BeanPostProcessor

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
   
   

		public void refresh() throws BeansException, IllegalStateException {
   
   
					// 初始化BeanProcessor来拦截Bean的创建
					registerBeanPostProcessors(beanFactory);
	
					// 初始化所有剩下的非懒加载的Bean,比如我们写的Service
					finishBeanFactoryInitialization(beanFactory);
		}
}

1.3 初始化切面方法跟切点

另外,AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessorSpring 会在Bean创建时调用其postProcessBeforeInstantiation方法对Bean进行处理。

在第一次调用该方法时,AnnotationAwareAspectJAutoProxyCreator会初始化切面

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
   
   
	
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
   
   
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
   
   
			//判断当前BeanName对应的Bean是否应该被代理
			//并将判断结果保存下来,避免后续的后处理方法重复计算
			//在第一次判断时,会在shouldSkip里扫描所有Bean进行切面初始化
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
   
   
				this.advisedBeans.put
Springaop源码分析 Springaop源码解析 阅读详情

相关推荐

seata源码分析之全局事务的开启跟xid的传递

概览 首先我们通过@GlobalTransactional这个注解开启一个全局事务,而GlobalTransactionScanner.wrapIfNecessary()会为所有方法上加了这个注解的bean注入一个包装了GlobalTransactionalInterceptor实例的advisor,然后返回一个代理对象。GlobalTransactionalInterceptor会在该bean的方法调用前进行拦截,判断是否开启全局事务 @Override protected Object wrapI

scientificCommunity的博客 6360

Spring AOP实现流程、源码分析

前言 AOP字面意思解释就是面向切面编程,面向切面编程是一种编程模型,我们知道JAVA是面向对象的也就是OOP,OOP这种面向对象的编程适用于定义纵向的关系,但是并不适用定义横向的关系。那么应对这种OOP的存在的这些不利,AOP面向切面的编程模型作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。 AO

程序员劝退师的博客 1027

seata源码分析之如何控制下游服务的提交与回滚

概览 seata client跟维持了一个连接,监听server端的消息,根据接到的消息判断是提交还是回滚。 客户端建立流程: GlobalTransactionScanner.afterPropertiesSet() GlobalTransactionScanner.initClient() TMClient.init TmRpcClient.getInstance new TmRpcClient new ...

scientificCommunity的博客 2166

spring aop源码分析

什么是AOP 面试中经常被问到什么是AOP,其实AOP是一种技术实现,或者说是一种实现标准,实现AOP的技术有多种,但是通常所说的AOP,大家会不自觉的想到spring aop,因为spring aop被问了很多次。本文想从源码的执行流程上来简单说说AOP的实现原理。 AOP底层技术实现 aop的底层技术其实就是大家熟知的代理,spring aop中的代理主要有两种,cglib代理和JDK动态代理...

congge 980

Spring Aop初始化源码分析

1 工程简介 1.1 pom <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.tar

qq_34125999的博客 4607

Spring框架AOP源码分析

Spring框架AOP源码分析 1.写在前面 做java开发的不可能不适用spring框架,我们都知道spring框架的两个基础功能就是Ioc和aop,相比来说Ioc会应用的更广泛一些,但aop同样重要,今天就来详细分析一下springaop的实现原理,会深入spring源码级别,对于spring不太熟悉的同学来说可能有点难,没有办法,分析源码就是这样,需要对框架有一定的应用经验并且比较熟悉原理,毕竟一个成熟的框架,特别是像spring这样的java技术栈统治级的框架。如果想学习spring的基本功能推荐

ChirsPaul3的博客 337

最详细的Spring Aop源码分析

转载自: https://javadoop.com/post/spring-aop-source 之前写过 IOC 的源码分析,那篇文章真的有点长,看完需要点耐心。很多读者希望能写一写 Spring AOP源码分析文章,这样读者看完 IOC + AOP 也就对 Spring 会有比较深的理解了。今天终于成文了,可能很多读者早就不再等待了,不过主要为了后来者吧。 本文不会像 IOC 源码分析...

qq_33285543的博客 386

Spring AOP介绍及源码分析

Spring AOP介绍及源码分析   spring4.0源码分析━━━(AOP实现)

wanxiaotao12-126-com 149

Spring源码解读之@Autowired如何解决循环依赖

文章目录@Autowired的what&how什么是循环依赖spring如何解决循环依赖 @Autowired的what&how 在spring框架下,我们可以通过@Autowired注解对属性或者方法参数进行标注,当spring ioc容器初始化时,会帮我们从容器中拿到对应的实例进行注入 什么是循环依赖 加入现在有两个Bean如下所示 public class BeanA { @Autowired private BeanB beanB; } public class B

scientificCommunity的博客 7694

踩坑日记之Gradle自定义JacocoReport跟Test task

起因 最近新写了一个项目,为了更好的保证项目输出的质量,引入了单元测试覆盖率统计框架Jacoco。由于gradle官网上的案例只有几个默认的task(test、JacocoTestReport等)的设置,而我希望能够额外为不同的层提供单独的test,也就发生了接下来这些有趣的事儿。 1. 为什么JacocoTestReport总是被SKIPPED 首先,我写了一个自定义的test。并且通过将finalizedBy指定为JacocoTestReport来让test执行完毕后自动执行JacocoTestRepo

scientificCommunity的博客 4085

vert.x源码解析之redis集成

文章目录前言vertx是什么vertx-redis-client是什么vertx-redis-client有哪些特性怎么使用vertx-redis-client几个核心类的使用方法RedisConnectionredisOptions各项主要配置的含义typemasterNameroleRedisClientSTANDALONE 前言 vertx是什么 vert.x是一个全异步框架,它是reactor线程模型的一种实现,通过内部的event bus跟event loop做到了处处皆异步。关于里面的细节,后面

scientificCommunity的博客 1619

Spring Cloud源码分析之eureka+feign远程调用

是一个REST (Representational State Transfer)服务,用于定位服务,以实现中间层服务器的负载平衡和故障转移,我们称此服务为Eureka服务器。Eureka还有一个基于java的客户端组件,Eureka客户端,这使得与服务的交互更加容易,同时客户端也有一个内置的负载平衡器,它执行基本的循环负载均衡。是一种声明式服务调用组件,它在的基础上做了进一步的封装。通过 Feign,我们只需要声明一个接口并通过注解进行简单的配置(类似于Dao接口上面的Mapper注解一样)即可实现对。

scientificCommunity的博客 1558

踩坑日记之Springfox+Kotlin lateinit引发NullPointException

相关技术栈 Kotlin1.5 Springboot2.5 Springfox3.0 起因 最近对接支付宝的电脑网站支付,需要定义一个支持表单Post提交的接口来接收支付宝的回调。在 定义完接口后发现Springfox初始化swagger时报了空指针,导致swagger api doc无法加载 分析 1. 报错位置 springfox.documentation.service.RequestParameter#equals springfox.documentation.schema.Example#e

scientificCommunity的博客 1265

Vertx实战之如何追踪异步函数调用

文章目录背景实现技术栈1. 同步or基于jdk的异步实现思路总结2. Vertx 中的实现1. eventbus上异步传递消息关于类加载2. 基于netty的异步io操作总结 背景 日常开发中我们经常需要排查各种系统问题,比如说因未处理的异常导致某次http请求返回了响应码为500的response、消息处理失败等。有时候我们可能直接通过异常本身给出的信息就能定位到问题,但有些时候我们可能必需要通过debug复原案发现场来定位问题所在,这个时候就需要知道这次事故的输入是什么(比如请求的参数)。 这个问题在同

scientificCommunity的博客 1071

Spring源码分析之事物管理

Spring事物详解,源码

scientificCommunity的博客 696

Spring Boot源码分析之自动装配

Spring Boot原理

scientificCommunity的博客 489
上一篇: spring mvc源码分析之请求分发
下一篇: Spring源码分析之事物管理
穹柏
博客等级 码龄9年 11粉丝 36原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值