AOP:面向切面编程,一种编程规范(规范形式),指导开发者如何组织程序结构(在不惊动原始设计的基础上,为其进行功能增强)
OOP:面向对象编程(做任何一个程序要用类来描述,运行的时候使用对象来执行)
Spring理念:无侵入式
*AOP核心概念
1.连接点:程序执行过程中的任意位置,粒度为执行方法抛出异常,设置变量等,在SpringAOP中,理解为方法的执行
2.切入点:匹配连接点的式子
在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
3.通知:在切入点处执行的操作,也就是共性功能
在SpringAOP中,功能最终以方法的形式呈现
4.切面:描述通知与切入点的对应关系
*AOP工作流程
1.Spring容器启动
2.读取所有切面配置中的切入点
3.初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
匹配失败,创建对象
匹配成功,创建原始对象(目标对象)的代理对象
4.获取bean执行方法
获取bean,调用方法并执行,完成操作
获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强内容,完成操作
目标对象:原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成工作的
代理(Proxy):目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现
*AOP的切入点表达式
切入点:要进行增强的方法
切入点表达式:要进行增强的方法的描述方式
标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法(参数)异常名)
例如:execution(public User com.sx.service.UserService.findId(int))
动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点
访问修饰符:public,private等可以省略
返回值
包名
类/接口名
方法名
参数
异常名:方法定义中抛出指定异常,可以省略
可以使用通配符描述切入点,快速描述
*:单个独立的任意符号,可以独立出现,也可以作为前缀,或者后缀额匹配符出现
execution(public * com.sx.*.UserService.find*(*))
匹配com.sx包下的任意包的UserService类或接口中的所有find为前缀的有参方法
..:多个连续的任意符号,可以独立出现,常用简化包名与参数的书写
execution(public User com..UserService.findId(..))
匹配com包下的任意包中的UserService中的findId的方法
*AOP通知获取数据
获取切入点方法参数
JoinPoint:适用于前置,后置,返回后,抛出异常通知
ProccedJointPoint:适用于环绕通知
获取切入点方法返回值
返回后通知
环绕通知
获取切入点方法运行异常信息
抛出异常后通知
环绕通知
SpringAop案例
1.导入坐标,aop坐标(自动导入),aspect(手工导入)
2.将共性功能抽取出来制作成独立的方法作为通知
3.定义切入点
3.1定义一个私有的空参无返回值空方法内容的方法
3.2声明当前方法作为切入点
4.绑定切入点与通知的关系(切面)
5.将当前类交由spring管理
6.声明当前类是一个切面类
7.使用注解开发的AOP
需求:打印当前输出语句时候显示系统时间
aop 这个包下都是对应的共同增强方法
package com.sx.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
//5.将当前类交由spring管理
@Component
//6.声明当前类是一个切面类
@Aspect
public class MyAdvice {
//3.定义切入点
//3.1定义一个私有的空参无返回值空方法内容的方法
//3.2声明当前方法作为切入点
// @Pointcut("执行到save方法时")
@Pointcut("execution(void com.sx.dao.impl.BookDaoImpl.*())")
private void pt(){}
//2.将共性功能抽取出来制作成独立的方法作为通知
//4.绑定切入点与通知的关系(切面)
@Before("pt()")
public void fn(){
System.out.println(System.currentTimeMillis());
}
}
config spring配置类
package com.sx.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("com.sx")
//7.使用注解开发的AOP
@EnableAspectJAutoProxy
public class SpringConfig {
}
Dao下的实现类
package com.sx.dao.impl;
import com.sx.dao.BookDao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
public void update(){
System.out.println("book dao update ...");
}
}
Dao下的接口
package com.sx.dao;
public interface BookDao {
public void save();
public void update();
}
App 启动类
package com.sx;
import com.sx.config.SpringConfig;
import com.sx.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = ctx.getBean(BookDao.class);
bookDao.save();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sx</groupId>
<artifactId>springaop_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--1.导入坐标,aop坐标(自动导入),aspect(手工导入)-->
<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>
</project>