AOP 即面向切面编程
什么是AOP
首先我们来理解什么是AOP
从这幅图来看,加入我们要实现一个登录功能需要在判断进入主页面中间加入一个权限验证功能。我们一般的操作是在源代码里面直接书写一个权限验证模块。AOP就是写一个单独的权限验证模块,切入进原来的代码,这个切入的过程就是AOP。
为什么使用AOP
具有解耦横切关注点、代码重用、增强现有代码、简化开发和配置灵活等优点。
重点是,可以在不修改源代码的情况下,可以对程序进行增强。
AOP相关概念
1.连接点:类当中的那些方法可以增强,那么这些方法就是连接点。
2.切入点:实际被增强的方法就是切入点。
3.增强(通知):增强功能的逻辑代码。
4.通知类型:
- 前置通知:增强的代码在切入点之前进行
- 后置通知:增强的代码在切入点之后进行
- 环绕通知:增强的代码在切入点之前之后都进行
- 异常通知:增强的代码在切入点执行发生异常后执行
- 最终通知:增强的代码在切入点之后进行,不管执行的代码成功与否都会执行,类似于 finally。
5.切面:是一个动作,将通知放到切入点的过程
AOP两种模式
1.xml配置模式
2.注解的形式
AOP XML配置模式
1.导入相关依赖
<!--Spring Aspects-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--aspectj-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.3</version>
</dependency>
aspectj--第三方提供的快速实现AOP的工具
2.来个demo(最终通知)
Application.xml文件
<?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: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">
<!-- 首先配置对象-->
<bean id="user" class="com.qcby.service.User"/>
<bean id="demo" class="com.qcby.service.Demo"/>
<!-- 设置切面 切面=切入点+通知 user-->
<aop:config>
<aop:aspect ref="demo">
<aop:after method="权限验证" pointcut="execution(public void com.qcby.service.User.判断())"/>
</aop:aspect>
</aop:config>
</beans>
User 切入点
public class User {
//切入点
public void 判断(){
System.out.println("这里判断登录是否正常");
}
}
Demo 切入的方法
@Controller(value = "demo")
public class Demo {
public void 权限验证(){
System.out.println("进行权限验证");
}
}
Test 类
public class SpringTest {
@Test
public void run1(){
ApplicationContext context = new ClassPathXmlApplicationContext("Application.xml");
User user = (User) context.getBean("user");
user.判断();
}
}
最后的效果
3.切入点的表达式
在配置切入点的时候,需要定义表达式,具体展开如下
--切入点表达式的格式如下:
execution([修饰符][返回值类型][类全路径][方法名([参数])])
修饰符可以省略不写,不是必须要出现的。
返回值类型是不能省略不写的,根据你的方法来编写返回值,可以使用*代替。
--包名,类名,方法名,参数的规则如下:
例如:com.qcby.demo3.BookDaolmpl.save()
首先包名,类名,方法名是不能省略不写的,但是可以使用*代替
中间的包名可以使用*号代替
类名也可以使用*号代替,也有类似的写法:*Daolmpl
方法也可以使用*号代替
参数如果是一个参数可以使用*号代替,如果想代表任意参数使用,多个参数可以用..代替
4.各类通知的xml配置:
环绕通知
目标方法执行前后都可以进行增强。目标对象的方法需要进行手动增强。
<aop:around method="around" pointcut="execution(* com.*.User.add(..))"/>
最终通知
目标方法执行成功或者失败,都会进行通知
<aop:after method="after" pointcut="execution(* com.*.User.add(..))"/>
前置通知
目标方法执行前进行通知
<aop:before method="before" pointcut="execution(public void com.aopImpl.User.add())"/>
后置通知
目标方法执行后进行通知
<aop: after-returning method="afterReturning" pointcut="execution(public void com.aopImpl.User.add())"/>
异常通知
目标方法执行失败后,进行通知(发生异常的时候才会执行否则不执行)
<aop: after-throwing method="afterThrowing" pointcut="execution(public void com.aopImpl.User.add())"/>
AOP 注解的形式
1.开启扫描
Application文件
<!--开启注解扫描-->
<context:component-scan base-package="com.gcby.service"/>
2.加上相关注解
Demo文件:
@Aspect表明它是一个通知类
User 文件:
3.开启对通知类的扫描
Application文件
<aop:aspectj-autoproxy/>
4.添加通知的注解
在此一并写完(就不单独举例了..)