一、AOP
1. AOP简介
问题导入
问题1:AOP的作用是什么?
问题2:连接点和切入点有什么区别,二者谁的范围大?
问题3:请描述什么是切面?
1.1 AOP简介和作用
AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构
OOP(Object Oriented Programming)面向对象编程
作用:在不惊动原始设计的基础上为其进行功能增强。简单的说就是在不改变方法源代码的基础上对方法进行功能增强。
Spring理念:无入侵式/无侵入式
1.2 AOP中的核心概念
连接点(JoinPoint):正在执行的方法,例如:update()、delete()、select()等都是连接点。
切入点(Pointcut):进行功能增强了的方法,例如:update()、delete()方法,select()方法没有被增强所以不是切入点,但是是连接点。
在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
一个具体方法:com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
通知(Advice):在切入点前后执行的操作,也就是增强的共性功能
在SpringAOP中,功能最终以方法的形式呈现
通知类:通知方法所在的类叫做通知类
切面(Aspect):描述通知与切入点的对应关系,也就是哪些通知方法对应哪些切入点方法。
2. AOP入门案例【重点】
问题导入
问题1:在通知方法中如何定义切入点表达式?
问题2:如何配置切面?
问题3:在配置类上如何开启AOP注解功能?
2.1 AOP入门案例思路分析
案例设定:测定接口执行效率
简化设定:在接口执行前输出当前系统时间
开发模式:XML or 注解
思路分析:
导入坐标(pom.xml)
制作连接点方法(原始操作,dao接口与实现类)
制作共性功能(通知类与通知)
定义切入点
绑定切入点与通知关系(切面)
2.2 AOP入门案例实现
【第一步】导入aop相关坐标
<dependencies> <!--spring核心依赖,会将spring-aop传递进来--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> <!--切入点表达式依赖,目的是找到切入点方法,也就是找到要增强的方法--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies>
【第二步】定义dao接口与实现类
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管理的bean @Component public class MyAdvice { public void method(){ System.out.println(System.currentTimeMillis()); } }
【第四步】定义切入点表达式、配置切面(绑定切入点与通知关系)
//通知类必须配置成Spring管理的bean @Component //设置当前类为切面类类 @Aspect public class MyAdvice { //设置切入点,@Pointcut注解要求配置在方法上方 @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt(){} //设置在切入点pt()的前面运行当前操作(前置通知) @Before("pt()") public void method(){ System.out.println(System.currentTimeMillis()); } }
【第五步】在配置类中进行Spring注解包扫描和开启AOP功能
@Configuration @ComponentScan("com.itheima") //开启注解开发AOP功能 @EnableAspectJAutoProxy public class SpringConfig { }
【第六步】测试类和运行结果
public class App { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); BookDao bookDao = ctx.getBean(BookDao.class); bookDao.update(); } }
3. AOP工作流程
问题导入
什么是目标对象?什么是代理对象?
3.1 AOP工作流程
Spring容器启动
读取所有切面配置中的切入点
初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
匹配失败,创建原始对象
匹配成功,创建原始对象(目标对象)的代理对象
获取bean执行方法
获取的bean是原始对象时,调用方法并执行,完成操作
获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作
3.2 AOP核心概念
目标对象(Target):被代理的对象,也叫原始对象,该对象中的方法没有任何功能增强。
代理对象(Proxy):代理后生成的对象,由Spring帮我们创建代理对象。
3.3 在测试类中验证代理对象
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.getClass()); } }