什么是AOP
定义: 面向切面编程(面向方面编程)
咱们的编程语言从原始机器语言 到过程语言 再到面向对象,从始至终的目的就是为了让代码再加灵活,再加容易让人理解,构建代码更加简单。
面向对象的语言虽然已经非常优秀,但是在灵活性上总是有些不如人意,因此,现在出来了函数式编程,也出来了我们今天要给大家讲的AOP。而AOP的出来并不是要取代OOP(面向对象编程),它只是作为一个补充的角色过来,来解决一些咱们OOP解决不了(或者说很难解决)的一些代码。
AOP的使用只存在于一些特定的场合(具有横切逻辑的应用场合),横切逻辑这个解释可能比较抽象,咱们说得再具体一点,AOP可以用于事务管理,日志管理,性能监测等地方
AOP术语
连接点(Joinpoint):程序执行的某一个特定位置,如类初始前后,方法的运行前后。而Spring只支持方法的连接点。
切点(Pointcut):切点可以定位到相应的连接点,一个切点可以定位多个连接点。
增强(Advice):又被称为通知,完成逻辑的增强。
目标对象(Target):增强逻辑织入的目标类。
引介(Introduction):特殊的增强,为类添加一些属性和方法。
织入(Weaving): 将增强添加到目标类的具体连接点上的过程。Spring使用动态代理织入。
代理(Proxy):一个类(原类)被织入增强(逻辑)后,就产生一个结果类,称为代理类。
切面(Aspect):由切点和增强组成
AOP联盟:众多开源AOP项目的联合组织,该组织定义了一套规范描述AOP标准。现在大部分的AOP实现都是使用AOP实现的标准。
Spring的Aop
早期Spring是自己实现AOP,后期改回使用标准的aspects(面向切面编程)。那么咱们说过,Spring使用动态代理织入。
Spring支持我们在方法的前后添加增强代码。
Aop的功能作用Spring的两个核心之一,也可以是Spring非常重要的功能。
前面我们两次提到了一个概念:动态代理。是的,要想了解Spring怎么实现Aop,我们得了解动态代理。那么想要了解动态代理,咱们需要先来研究一下:代理模式。
如果是由咱们自己来完成动态代理确实是非常麻烦,不过好在大家并不用太过担心,因为Spring已经帮咱们把困难的部分完成,我们只需要做一些简单的配置就可以完成相应的功能。
配置的时候一定要记住三个要素:何时,何地,做什么事
何时:在执行方法之前/之后/有异常…
何地:在哪些包中的哪些类的哪些方法上面执行
做什么事: 在UserServie中执行update方法之前添加日志
Spring实现AOP的方案
Spring实现Aop有两种方案:JDK与CGLIB,这里我们以JDK版本为例
1.配置文件
<!-- 组件搜索 -->
<context:component-scan base-package="cn.itsource.aopanno" />
<!-- 支持aop注解 -->
<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="cn.itsource.SpringAopAnnotation"/>
<aop:aspectj-autoproxy />
</beans>
2.事物管理器
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.test.annotation.Rollback;
@Component
@Aspect
public class AspectCurt {
//设置切点为service层下的所有文件所有类的所有方法
@Pointcut("execution(* cn.itsource.SpringAopAnnotation.service..*.*(..))")
public void aa() {
}
;
// @Before("aa()")前置通知
private void Begin() {
System.out.println("Begin");
}
// @After("aa()")最终通知
public void Close() {
System.out.println("Close");
}
// @AfterReturning("aa()")后置通知
public void Commit() {
System.out.println("Commit");
}
// @AfterThrowing("aa()")异常通知
public void Throws() {
System.out.println("Throws");
}
//环绕通知
@Around("aa()")
public Object around(ProceedingJoinPoint joinPoint) {
Object object = null;
try {
Begin();
object = joinPoint.proceed();
Commit();
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable throwable) {
Throws();
} finally {
Close();
}
return object;
}
}