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的坐标已经包含在了spring-context中去了
org.springframework spring-context 5.2.22.RELEASE org.aspectj aspectjweaver 1.9.4
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 {}
新建一个aop包,新建一个通知类MyAdvice
public class MyAdvice {public void method(){System.out.println(System.currentTimeMillis());}
}
在通知类的定义一个切入点使用一个@Pointcut()注解,注解括号里的内容如下
解释为执行到一个返回值为空,并且是指定路径下的方法时就说明这是一个切入点
@Pointcut("execution(void org.example.dao.BookDao.update())")public void pt(){}
使用一个@Before,意为在切入点方法之前执行method()
@Pointcut("execution(void org.example.dao.BookDao.update())")public void pt(){}@Before("pt()")public void method(){System.out.println(System.currentTimeMillis());}
使用两个注解@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配置类的注解
成功输出