目录
AOP 即面向切面编程,和 OOP(面向对象编程)类似,也是一种编程思想。
AOP 采取横向抽取机制(动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。
主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。
简单的说,AOP 的作用就是保证开发者在不修改源代码的前提下,为系统中的业务组件添加某种通用功能。AOP 就是代理模式的典型应用。
AOP 是 Spring 的核心之一,在 Spring 中经常会使用 AOP 来简化编程。在 Spring 框架中使用 AOP 主要有以下优势。
提供声明式企业服务,特别是作为 EJB 声明式服务的替代品。最重要的是,这种服务是声明式事务管理。
允许用户实现自定义切面。在某些不适合用 OOP 编程的场景中,采用 AOP 来补充。
可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时也提高了开发
目前最流行的 AOP 框架有两个
| 名称 | 说明 |
|---|---|
| Target(目标) | 指代理的目标对象。 |
| Pointcut(切入点) | 指要对哪些 Joinpoint 进行拦截,即被拦截的连接点。 |
| Advice(通知) | 指拦截到 Joinpoint 之后要做的事情,即对切入点增强的内容。 |
| Joinpoint(连接点) | 指那些被拦截到的点,在 Spring 中,指可以被动态代理拦截目标类的方法。 |
| Weaving(植入) | 指把增强代码应用到目标上,生成代理对象的过程。 |
| Proxy(代理) | 指生成的代理对象。 |
| Aspect(切面) | 切入点和通知的结合。 |
需要被代理的类,比如:userService。
是指那些可能被拦截的方法 比如:所有的方法。
已经被增强的连接点,在哪些类上,哪些方法上切入。
增强代码 (前置通知 、后置通知、返回后通知 、抛出异常通知、环绕通知)。
在方法执行的什么时候( 之前 之后 ...)做什么事情(方法)去。
| 通知 | 说明 |
|---|---|
| before(前置通知) | 通知方法在目标方法调用之前执行 |
| after(后置通知) | 通知方法在目标方法返回或异常后调用 |
| after-returning(返回后通知) | 通知方法会在目标方法返回后调用 |
| after-throwing(抛出异常通知) | 通知方法会在目标方法抛出异常后调用 |
| around(环绕通知) | 通知方法会将目标方法封装起来 |
把增强的方法应用到目标对象Target 来创建新的代理对象Proxy的过程。
是切入点(Pointcut)和通知(Advice)的结合,即在什么时候,什么地方,做什么增强。

- <dependency>
- <groupId>org.aspectjgroupId>
- <artifactId>aspectjweaverartifactId>
- <version>1.9.7version>
- dependency>
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-xxx.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-xxx.xsd ">
- beans>
- public void beforeAdvice(JoinPoint jp) {
- System.out.println("基于Spring AOP的前置增强处理.....");
- }
- public void afterReturnAdvice() {
- System.out.println("基于Spring AOP的后置返回增强处理.....");
- }
-
- public void afterAdvice() {
- System.out.println("基于Spring AOP的后置增强处理.....");
- }
- public void afterThrowAdvice() {
- System.out.println("基于Spring AOP的异常返回增强处理.....");
- }
-
- public Object aoundAdvice(ProceedingJoinPoint pt) {
- System.out.println("基于Spring AOP的环绕增强前置处理.....");
- Object res = null;
- try {
- res=pt.proceed();//调用目标方法 返回目标方法的返回结果
- } catch (Throwable e) {
- e.printStackTrace();
- }
- System.out.println("基于Spring AOP的环绕增强后置处理.....");
- return res;
- }
- <bean id="xxx" class="xxx.xxx"/>
-
- <aop :config>
-
- <aop:aspect ref="xxx">
- ...
- aop:aspect>
- aop:config>
用来定义一个切入点,当 元素作为 元素的子元素定义时,表示该切入点是全局切入点,它可被多个切面所共享;当 元素作为 元素的子元素时,表示该切入点只对当前切面有效。
- <aop :config>
- <aop:pointcut id="point" expression="execution(* com.yjy.service.UserServiceImpl.*(..))"/>
-
- <aop:aspect ref="diyPoint">
- <aop:pointcut id="point" expression="execution(* com.yjy.service.UserServiceImpl.*(..))"/>
-
- <aop:before pointcut-ref="point" method="..."/>
-
- <aop:after-returning pointcut-ref="point" method="..."/>
-
- <aop:around pointcut-ref="point" method="..."/>
-
- <aop:after-throwing pointcut-ref="point" method="..."/>
-
- <aop:after pointcut-ref="point" method="..."/>
在 Spring 中,尽管使用 XML 配置文件可以实现 AOP 开发,但是如果所有的相关配置都集中在配置文件中,势必会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。
| 名称 | 说明 |
|---|---|
| @Aspect | 用于定义一个切面。 |
| @Pointcut | 用于定义一个切入点。 |
| @Before | 用于定义前置通知,相当于 BeforeAdvice。 |
| @AfterReturning | 用于定义后置通知,相当于 AfterReturningAdvice。 |
| @Around | 用于定义环绕通知,相当于MethodInterceptor。 |
| @AfterThrowing | 用于定义抛出通知,相当于ThrowAdvice。 |
| @After | 用于定义最终final通知,不管是否异常,该通知都会执行。 |
| @DeclareParents | 用于定义引介通知,相当于IntroductionInterceptor(不要求掌握)。 |
@Before(value = "execution(* com.yjy.spring.impl..(..))")
@After(value = "execution(* com.yjy.spring.impl..(..))")
@AfterReturning(value="execution(* com.yjy.service.impl..(..))")
@AfterThrowing(value="execution(* com.yjy.service.impl..(..))")
@Around(value="execution(* com.yjy.service.impl..(..))")