一、AOP术语
二、AOP准备操作
1
、
Spring
框架一般都是基于
AspectJ
实现
AOP
操作
(
1
)
AspectJ
不是
Spring
组成部分,独立
AOP
框架,一般把
AspectJ
和
Spring
框架一起使
用,进行
AOP
操作
导入AspectJ的jar包即可使用
2
、基于
AspectJ
实现
AOP
操作
(
1
)基于
xml
配置文件实现
(
2
)基于注解方式实现(开发最常使用)
3
、在项目工程里面引入
AOP
相关依赖
![](https://i-blog.csdnimg.cn/blog_migrate/78f9553a0987cd15c65e8645676154b8.png)
4
、切入点表达式
(
1
)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(
2
)语法结构:
execution([
权限修饰符
] [
返回类型
] [
类全路径(包+类名)
] [
方法名称
]([
参数列表
]) )
举例
1
:对
com.atguigu.dao.BookDao
类里面的
add
进行增强
execution(* com.atguigu.dao.BookDao.add(..))
举例
2
:对
com.atguigu.dao.BookDao
类里面的所有的方法进行增强
execution(* com.atguigu.dao.BookDao.* (..))
举例
3
:对
com.atguigu.dao
包里面所有类,类里面所有方法进行增强
execution(* com.atguigu.dao.*.* (..))
三、AOP 操作(AspectJ 注解)
1、创建待增强类User2,在类里面定义待增强方法add()(add()也称为切入点)
package AOP2;
import org.springframework.stereotype.Component;
@Component//默认此类id为user2
public class User2 {
public void add() {
System.out.println("add.......");
}
}
2
、创建增强类(编写增强逻辑)
package AOP2;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect //表示生成代理对象
public class User2Proxy {
@Before(value = "execution(* AOP2.User2.add(..))")//@Before表示前置通知,括号内为增强表达式
public void before() {
System.out.println("before......前置通知");
}
//最终通知
@After(value = "execution(* AOP2.User2.add(..))")
public void after() {
System.out.println("after......最终通知");
}
//后置通知(返回通知)
@AfterReturning(value = "execution(* AOP2.User2.add(..))")
public void afterReturning() {
System.out.println("afterReturning.........后置通知(返回通知)");
}
//异常通知
@AfterThrowing(value = "execution(* AOP2.User2.add(..))")
public void afterThrowing() {
System.out.println("afterThrowing.........异常通知");
}
//环绕通知
@Around(value = "execution(* AOP2.User2.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前.........");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后.........");
}
}
3
、进行通知的配置
xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 这三个名称空间与<context:component-scan>对应
xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 这三个名称空间与<aop:aspectj-autoproxy>对应
<?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="AOP2"></context:component-scan>
<!--开启Aspect生成代理对象-->
<!--从AOP2中找有没有@Aspect注解的类,生成其代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
4、测试
package AOP2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AOP2Test {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
User2 user2 = context.getBean("user2", User2.class);//默认User2的id为user2
user2.add();//即增强后的add()
}
}
5
、相同的切入点抽取
- 上面增强类中不同不同的增强方法的切入点都是一样的,即增强表达式相同。为了简洁,所以可以抽取相同的切入点
- @Pointcut表示公共切入点方法的注解,只需把下面各个方法的增强表达式换成此方法名即可
-
package AOP2; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component @Aspect //表示生成代理对象 public class User2Proxy { @Pointcut(value = "execution(* AOP2.User2.add(..))") public void pointcut(){} @Before(value = "pointcut()")//@Before表示前置通知,括号内为增强表达式 public void before() { System.out.println("before......前置通知"); } //最终通知 @After(value = "pointcut()") public void after() { System.out.println("after......最终通知"); } //后置通知(返回通知) @AfterReturning(value = "pointcut()") public void afterReturning() { System.out.println("afterReturning.........后置通知(返回通知)"); } //异常通知 @AfterThrowing(value = "pointcut()") public void afterThrowing() { System.out.println("afterThrowing.........异常通知"); } //环绕通知 @Around(value = "pointcut()") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕之前........."); //被增强的方法执行 proceedingJoinPoint.proceed(); System.out.println("环绕之后........."); } }
6 、有多个增强类多同一个方法进行增强,设置增强类优先级
在增强类上面添加注解
@Order(
数字类型值
)
,数字类型值越小优先级越高
- 重新建一个增强类,加上注解@Order(2),在之前增强类上也加上@Order(1),则会先执行之前的增强类中的before()方法
package AOP2;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(2)
public class User2Proxy2 {
@Before(value = "execution(* AOP2.User2.add(..))")
public void before(){
System.out.println("before2.....");
}
}