Spring学习笔记(AOP)
什么是AOP
AOP,即面向切面编程,是OOP的补充,它也提供了模块化。在面向对象编程中,关键的单元是对象,AOP的关键单元是切面。
说得简单点,AOP就是一个能够在不修改源代码的情况下做功能增强的一种编程思想
AOP术语
-
连接点
可以增强的方法
-
切入点
实际上被增强的方法
-
通知(增强)
实际增强的逻辑部分 通知有多种类型: - 前置通知 在连接点之前执行的Advice,除非他抛出异常,否则没有能力中断执行流。使用@Before这个注解可以使用这个Advice - 后置通知 和finally很像,无论程序是因为什么原因终端执行的,最终都会执行这个Advice。通过@After注解实现 - 环绕通知 在连接点的前后都要执行,通过@Around注解实现 - 异常通知 被增强的方法出现异常时执行,通过@After Throwing注解来实现 - 返回之后通知 在连接点正常结束之后执行的Advice。例如,如果一个方法没有抛出异常正常返回。通过 @AfterReturning 注解使用它
-
切面
AOP核心就是切面,它将多个类的通用行为封装成可重用的模块,该模块含有一组API提供横切功能。比如,一个日志模块可以被称作日志的AOP切面。根据需求的不同,一个应用程序可以有若干切面。在Spring AOP中,切面通过带有@Aspect注解的类实现
-
AOP代理
由AOP框架创建的对象,用于实施Aspect。在Spring FrameWork中,AOP代理将是JDK动态代理或者CGLIB代理
AOP实现
基于Java的AOP的实现方式主要有:AspectJ . Spring AOP . JBoss AOP
切入点表达式的写法:
execution([权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])
eg:
对com.Async.dao.BookDao类里边的add方法进行增强:
execution(* com.Async.dao.BookDao.add(..))
实现AOP的步骤:(假设我们以User类的add方法为要增强的方法)
-
创建类,在类里边定义方法,添加注解创建类的对象
@Component public class User{ public void add(){ System.out.println("add.....") } }
-
创建增强类,编写增强逻辑
@Component @Aspect public UserProxy{ // 相同切入点的提取 @Pointcut(value = "execution(* com.Async.spring5.User.add(..))") public void Pointcut(){ } // 前置方法 @Before public void before(){ System.out.println("before.....") } // 返回通知 @AfterReturning(value = "execution(* com.Async.spring.User.add(..))") public void afterReturning(){ System.out.println("afterReturning..."); } // 异常通知 @AfterThrowing(value = "execution(* com.micah.spring.aopnno.User.add(..))") public void afterThrowing(){ System.out.println("afterThrowing..."); }
-
添加项目配置文件(也可以用注解来写一个类代理配置文件)
<?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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启注解扫描 --> <context:component-scan base-package="com.micah.spring"></context:component-scan> <!-- 开启Aspect生成代理对象--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
-
测试结果
@Test public void testAopAnno(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); User user = context.getBean("user", User.class); user.add(); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRTjbUHG-1651484387132)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220502173426424.png)]
5.如果有多个增强类对同一个方法进行增强:可以用@Order注解来设置优先级,Order里边的值为自然数,值越小优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy
AspectJ配置文件
<!--配置 aop 增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(*com.Async.spring.aopxml.Book.buy(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>