Spring源码剖析——AOP篇

初识AOP

简而言之的了解下什么是AOP:AOP(Aspect Oriented Programming)称为面向切面编程,在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程(这里尤指Spring AOP)。
为什么使用AOP?回答这类的问题,就从它最常使用的场景入手。
比如我现在有一段校验的代码,判断数据的有效性,好多地方都会用到,于是,为了保证功能的正确性,每个使用到的地方都加上这段代码。
AOP
重复性代码太不美观和高效了,于是将校验逻辑单独提取出去,这样就好多了。
AOP
这样虽然有了一些切面编程的意思,但是如果现在业务代码已经写完了,只是想补充上这段校验逻辑,如果以这种方式去实现,那势必要改动这个类,加上这段校验。而AOP的实现是将校验逻辑独立出去,运行时在业务实现方法前插入校验逻辑,其表现为下图的样子。
AOP
这样的好处显而易见的,它不会破坏原有的代码逻辑,也无需改动业务代码,可以使业务方法更专注于业务实现。

AOP的基本概念

关于Spring AOP,有很多概念,先来梳理一下:

  • Joint point(连接点):程序执行过程中明确的点,一般是方法的调用。被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。它自身还可以嵌套其它 joint point。简单点理解就是可以认为一个方法的执行就是一个连接点,它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。
  • Pointcut(切点):表示一组 joint point,在程序中主要体现为书写切入点表达式,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
  • Advice(增强):Advice 定义了在 Pointcut 里面定义的具体要增强的操作,包括before(前置),after(后置),afterReturning(最终),afterThrowing(异常),around(环绕),以此区别在何处增强。
  • Aspect(切面): 通常是一个类,类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
  • Target(目标对象):织入 Advice 的目标对象.。
  • Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程,在编译时(例如使用AspectJ编译器)、加载时或运行时完成。
  • AOP Proxy(AOP代理):AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

使用AOP的准备工作

必要的jar包还是需要引入的,最简单的,就是直接将spring-boot-starter-aop引入就好了

	<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
      <version>2.3.1.RELEASE</version>
    </dependency>

通过Java启用@AspectJ支持@Configuration,需要在AppConfig类上添加@EnableAspectJAutoProxy 注释:

	@Configuration
	@EnableAspectJAutoProxy
	public class AppConfig {
	
	}

当然,也可以使用xml配置,需要加入aop:aspectj-autoproxy:

	<aop:aspectj-autoproxy/>

AOP Demo

趁热打铁,来写个例子
先准备一个实现类,在StudyService 接口中定义getLearningontents()方法

	@Component
	public class StudyServiceImpl implements StudyService {
	    @Override
	    public String getLearningontents() {
	        System.out.println("方法执行中...");
	        return "aop";
	    }
	}

想要实现切面,就要有一个类,引入@Aspect让其生效。接下来,定义一个切入点,并指定在什么位置增强,于是有了下面的代码:

	@Component
	@Aspect
	public class StudyAspect {
	
	    @Pointcut("execution(* com.study.ioc.service.*.*(..))")
	    public void studyTransfer(){};
	
	    @Before("studyTransfer()")
	    public void before(){
	        System.out.println("执行前...");
	    }
	
	    @After("studyTransfer()")
	    public void after(){
	        System.out.println("执行后...");
	    }
	
	}

execution(* com.study.ioc.service..(…))是一种切入点表达式,表示service包中定义的任何方法都执行。下面的@Before和@After指明对于哪个切入点进行通知。
在App类中测试一下:

	public class App {
	    public static void main(String[] args) {
	        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
	        StudyService studyService = ac.getBean(StudyService.class);
	        System.out.println(studyService.getLearningontents());
	
	    }
	}
	
	执行结果:  执行前...
			  方法执行中...
			  执行后...
			  aop

到此,一个简单的AOP实现就做好了。

AOP的基础理论和基本使用就介绍到这,有关Spring对AOP的实现部分且看后续

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值