需求分析
案例设定:测算接口执行效率,但是这个案例稍微复杂了点,我们对其进行简化。
简化设定:在方法执行前输出当前系统时间。
思路分析
需求明确后,具体该如何实现,都有哪些步骤,我们先来分析下:
1.导入坐标(pom.xml)
2.制作连接点(原始操作,Dao接口与实现类)
3.制作共性功能(通知类与通知)
4.定义切入点
5.绑定切入点与通知关系(切面)
环境准备
- 创建一个Maven项目
- pom中添加spring依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
- 添加BookDao和BookDaoImpl类
public interface BookDao {
public void save();
public void update();
}
@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 ...");
}
}
- 创建Spring的配置类
@Configuration
@ComponentScan("com.mzh")
public class SpringConfig {
}
- 编写App运行类
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = ctx.getBean(BookDao.class);
bookDao.save();
}
}
说明
- 目前打印save方法的时候,因为方法中有打印系统时间,所以运行的时候是可以看到系统时间
- 对于update方法来说,就没有该功能
- 我们要使用SpringAOP的方式在不改变update方法的前提下让其具有打印系统时间的功能
AOP实现步骤
步骤1:添加依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
步骤2:定义接口与实现类
环境准备的时候,BookDaoImpl已经准备好,不需要做任何修改
步骤3:定义通知类和通知
通知就是将共性功能抽取出来后形成的方法,共性功能指的就是当前系统时间的打印。
public class MyAdvice {
public void method(){
System.out.println(System.currentTimeMillis());
}
}
类名和方法名没有要求,可以任意
步骤4:定义切入点
public class MyAdvice {
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
public void method(){
System.out.println(System.currentTimeMillis());
}
}
步骤5:制作切面
切面是用来描述通知和切入点之间的关系
public class MyAdvice {
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
步骤6:将通知类配给容器并标识其为切面类
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
步骤7:开启注解格式AOP功能
@Configuration
@ComponentScan("com.itheima")
@EnableAspectJAutoProxy
public class SpringConfig {
}
步骤8:运行程序
public class App {
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = app.getBean(BookDao.class);
bookDao.update();
}
}
知识点1:@EnableAspectJAutoProxy
名称 | @EnableAspectJAutoProxy |
---|---|
类型 | 配置类注解 |
位置 | 配置类定义上方 |
作用 | 开启注解格式AOP功能 |
知识点2:@Aspect
名称 | @Aspect |
---|---|
类型 | 类注解 |
位置 | 切面类定义上方 |
作用 | 设置当前类为AOP切面类 |
知识点3:@Pointcut
名称 | @Pointcut |
---|---|
类型 | 方法注解 |
位置 | 切入点方法定义上方 |
作用 | 设置切入点方法 |
属性 | value(默认):切入点表达式 |
知识点4:@Before
名称 | @Before |
---|---|
类型 | 方法注解 |
位置 | 通知方法定义上方 |
作用 | 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行 |