Spring有两个核心的概念,一个是IOC/DI
,一个是AOP
。
AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构
AOP是在不改原有代码的前提下对其进行增强。
1,一个简单的例子,只增强一个方法,AOP实现步骤
BookDaoImpl中有两个方法,分别是save和update,我们要增强的是update方法,增加打印系统时间。具体如下:
步骤1:添加依赖
pom.xml
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version>
</dependency>
- 因为
spring-context
中已经导入了spring-aop
,所以不需要再单独导入spring-aop
- 导入AspectJ的jar包,AspectJ是AOP思想的一个具体实现,Spring有自己的AOP实现,但是相比于AspectJ来说比较麻烦,所以我们直接采用Spring整合ApsectJ的方式进行AOP开发。
步骤2:定义接口与实现类
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 ...");}
}
}
步骤3:定义通知类和通知
通知就是将共性功能抽取出来后形成的方法,共性功能指的就是当前系统时间的打印。
public class MyAdvice {public void method(){System.out.println(System.currentTimeMillis());}
}
类名和方法名没有要求,可以任意。
步骤4:定义切入点
BookDaoImpl中有两个方法,分别是save和update,我们要增强的是update方法,该如何定义呢?
public class MyAdvice {@Pointcut("execution(void com.itheima.dao.BookDao.update())")private void pt(){}public void method(){System.out.println(System.currentTimeMillis());}
}
说明:
- 切入点定义依托一个不具有实际意义的方法pt()进行,即无参数、无返回值、方法体无实际逻辑。
- execution及后面编写的内容,后面会有章节专门去学习。
步骤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());}
}
绑定切入点与通知关系,并指定通知添加到原始连接点的具体执行位置
说明:@Before翻译过来是之前,也就是说通知会在切入点方法执行之前执行,除此之前还有其他四种类型,后面会讲。
步骤6:将通知类配给容器并标识其为切面类@Aspect
@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 ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);bookDao.update();System.out.println(bookDao);System.out.println(bookDao.getClass());bookDao.save();}
}
看到在执行update方法之前打印了系统时间戳,说明对原始方法进行了增强,AOP编程成功。
知识点1:@EnableAspectJAutoProxy
名称 | @EnableAspectJAutoProxy |
---|---|
类型 | 配置类注解 |
位置 | 配置类定义上方 |
作用 | 开启注解格式AOP功能 |
知识点2:@Aspect
名称 | @Aspect |
---|---|
类型 | 类注解 |
位置 | 切面类定义上方 |
作用 | 设置当前类为AOP切面类 |
知识点3:@Pointcut
名称 | @Pointcut |
---|---|
类型 | 方法注解 |
位置 | 切入点方法定义上方 |
作用 | 设置切入点方法 |
属性 | value(默认):切入点表达式 |
知识点4:@Before
名称 | @Before |
---|---|
类型 | 方法注解 |
位置 | 通知方法定义上方 |
作用 | 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行 |
[说明]:内容主要来源黑马程序员网上资源学习