AOP
目录
概述
概述
aspect oritented programming : 面向切面编程
aop是oop的延续,将oop中重复代码抽取成一个独立模块(通知),被抽取了重复代码的模块(切入点),利用动态代理技术,将通知织入到切入点动态执行的过程,就叫做AOP。
-
作用
-
在不修改源码的情况下,对原有方法进行增强。
-
-
好处
-
提高了程序的复用性
-
提高了程序的维护性
-
提高了程序的开发效率
-
AOP名词解释
-
链接点
-
Joinpoint
-
类中的所有方法
-
-
切入点
-
pointcut
-
具有共性功能的方法
-
-
通知
-
advice
-
将共性功能抽取出来制作成独立的方法
-
-
切面
-
aspect
-
通知和切入点的位置关系
-
-
通知对象
-
包含通知的类对象
-
-
目标对象
-
包含切入点的类对象
-
-
织入
-
将通知动态地加入到原始字节码文件(切入点)中
-
通知类别
名称 | 标签 | 说明 |
---|---|---|
前置通知 | aop:before | 在切入点之前执行 |
正常后置通知 | aop:after-returning | 在切入点之后执行,当切入点没有异常才执行 |
环绕通知 | aop:around | 在切入点之前执行,在切入点之后执行 |
异常后置通知 | aop:after-throwing | 在切入点之后执行,当切入点有异常才执行 |
后置通知 | aop:after | 在切入点之后执行,不管切入点是否有异常都执行 |
SpringAOP入门案例
-
开发步骤
-
引入依赖
-
编写目标类UserServiceImpl
-
编写切入点
-
-
编写通知类
-
编写通知
-
-
配置切面
-
-
代码实现
-
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--扫描注解--> <context:component-scan base-package="com.qzw"></context:component-scan> <aop:config> <!-- 配置切面 : 通知和切入点的位置关系 id : 通知类 method : 通知 pointcut : 切入点 --> <aop:aspect ref="myAdvice"> <aop:before method="checkPermission" pointcut="execution(void com.qzw.service.impl.UserServiceImpl.addUser())"></aop:before> <aop:after method="addLog" pointcut="execution(void com.qzw.service.impl.UserServiceImpl.addUser())" ></aop:after> <aop:before method="checkPermission" pointcut="execution(void com.qzw.service.impl.UserServiceImpl.deleteUser())"></aop:before> <aop:after method="addLog" pointcut="execution(void com.qzw.service.impl.UserServiceImpl.deleteUser())" ></aop:after> </aop:aspect> </aop:config> </beans>
基于XMLAOP实现:切入点
-
基于XMLAOP实现: 切面
-
@Component public class MyAdvice2 { public void before(){ System.out.println("before : 前置通知"); } /** * 在切入点之后执行,且切入点没有异常才执行 */ public void afterReturning(){ System.out.println("afterReturning : 正常后置通知"); } /** * 在切入点之前执行,在切入点之后执行 */ public void around(ProceedingJoinPoint pjp){//链接点:目标类中的所有方法(包含切入点) System.out.println("around : 环绕通知之前"); try { pjp.proceed();//执行正在执行的链接点 } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println("around : 环绕通知之后"); } /** * 在切入点之后执行,且切入点有异常才执行 */ public void afterThrowing(){ System.out.println("afterThrowing : 异常后置通知"); } /** * 在切入点之后执行,不管怎么样都会执行 */ public void after(){ System.out.println("after : 后置通知"); } }
基于注解的AOP实现:
-
开发步骤
-
开启支持AOP注解
-
通知类上使用@Aspect
-
通知上使用@Around、@Before、@AfterReturning、@AfterThrowing、@After
xml配置:开启支持AOP注解
-
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="com.qzw"></context:component-scan> <!--开启aop注解支持--> <aop:aspectj-autoproxy ></aop:aspectj-autoproxy> </beans>
切面:通知类上使用@Aspect
-
@Component @Aspect//配置切面 : 通知和切入点关系 public class Advice2 { @Before("execution(* *..*Service.add*(..))") public void before(){ System.out.println("before : 前置通知"); } @AfterReturning("execution(* *..*Service.add*(..))") public void afterReturning(){ System.out.println("afterReturning : 正常后置通知"); } @Around("execution(* *..*Service.add*(..))") public void around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("环绕通知之前"); pjp.proceed(); System.out.println("环绕通知之后"); } @AfterThrowing("execution(* *..*Service.add*(..))") public void afterThrowing(){ System.out.println("afterThrowing : 异常后置通知"); } @After("execution(* *..*Service.add*(..))") public void after(){ System.out.println("after : 后置通知"); } }