AOP:面向切面编程,一种编程范式,指导开发者如何组织程序结构
作用:在不惊动原始设计的基础上进行功能增强
Spring理念:无侵入式编程
比如测试一个方法的万次执行时间,原本没有Aop需要这样写
public void save() {
Long st=System.currentTimeMillis();
for(int i=0;i<10000;i++)
System.out.println("service_save...");
Long et=System.currentTimeMillis();
Long tt=et-st;
System.out.println("执行万次消耗时间:"+tt);
}
有了AOP以后在源代码里面就可以像下面这样写也能测试万次执行时间,本质上是提供接口给外部去测试。这就没有改动源码就可以增加一个万次测试时间的功能。
public void save() {
System.out.println("service_save...");
}
对于上述功能的实现,需要将下列东西抽取出来单独封窗
public void method() {
Long st=System.currentTimeMillis();
for(int i=0;i<10000;i++) {
//通过接口调用原始方法
}
Long et=System.currentTimeMillis();
Long tt=et-st;
System.out.println("执行万次消耗时间:"+tt);
}
AOP核心概念:
原始方法也叫做连接点,要追加功能的方法叫做切入点,而追加同一个功能的代码,也就是上面这段封装的公共代码被称为“通知”,通知也有一个对应的通知类
切入点就是要增强的方法,通知就是增强的内容
将通知和切入点绑定到一起的东西就叫做切面
切面:对于通知和切入点之间的关系描述
上述图的流程就是首先找程序中的共性功能写一个通知类,在通知类中定义一个方法叫做通知,而连接点是所有方法,而切入点是被选中要增强的方法,因为不是所有方法都需要增强,将切入点和通知绑定后就得到一个关系——切面:在哪些切入点上执行哪些通知
AOP入门案例
案例流程
项目结构
1.导入坐标
aop的坐标已经包含在了spring-context中去了
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.22.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId> <!---->
<version>1.9.4</version>
</dependency>
2.制作连接点方法(原始操作,Dao层接口和实现类)
Dao层接口的一个实现类
@Repository
public class BookDaoImpl implements BookDao {
public void save(){
System.out.println(System.currentTimeMillis());
System.out.println("book dao save...");
}
public void update(){
System.out.println("book dao update...");
}
}
再在SpringConfig定义一个基础的配置类
@Configuration
@ComponentScan("org.example")
public class SpringConfig {
}
3.制作共性功能(通知类与通知)
新建一个aop包,新建一个通知类MyAdvice
public class MyAdvice {
public void method(){
System.out.println(System.currentTimeMillis());
}
}
4.定义切入点
在通知类的定义一个切入点使用一个@Pointcut()注解,注解括号里的内容如下
解释为执行到一个返回值为空,并且是指定路径下的方法时就说明这是一个切入点
@Pointcut("execution(void org.example.dao.BookDao.update())")
public void pt(){}
5.绑定切入点与通知关系(切面)
使用一个@Before,意为在切入点方法之前执行method()
@Pointcut("execution(void org.example.dao.BookDao.update())")
public void pt(){}
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
6.将通知类交给spring进行管理,并告知spring这是个做AOP的类
使用两个注解@Component(交给spring管理) @Aspect告诉spring这是个通知类
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void org.example.dao.BookDao.update())")
public void pt(){}
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
然后还要告诉spring整个程序是用注解开发的AOP,在SpringConfig配置类上使用一个新注解
@EnableAspectJAutoProxy 该注解启动了通知类里面的@Aspect,然后@Aspect又让spring去注意到通知类里里面的内容
SpringConfig配置类的注解
总结测试
成功输出