说明:使用注解方式实现AOP切面。
什么是AOP?
- 面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能。
- AOP底层使用动态代理。
AOP术语
-
连接点
类里面哪些方法可以被增强,这些方法称为连接点。 -
切入点
实际被真正增强的方法,称为切入点。 -
通知(增强)
实际增强的逻辑部分称为通知。
多种类型通知:- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
-
切面
是个动作,把通知应用到切入点的过程。
AOP案例实操
- AOP 相关依赖
- 切入点表达式
切入点表达式作用:知道对哪个类里面的哪个方法进行增强。
语法结构:
execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )
举例 1:对 com.evan.dao.BookDao 类里面的 add 进行增强
execution(* com.evan.dao.BookDao.add(..))
举例 2:对 com.evan.dao.BookDao 类里面的所有的方法进行增强
execution(* com.evan.dao.BookDao.* (..))
举例 3:对 com.evan.dao 包里面所有类,类里面所有方法进行增强
execution(* com.evan.dao.*.* (..))
1、创建User类
public class User {
public void add() {
System.out.println("add..");
}
}
2、创建UserProxy增强类
@Component //创建该类对象加入到spring容器中
@Aspect //生成代理类对象
@Order(1) //增强类优先级
public class UserProxy {
//前置通知:在被代理的目标方法前执行
@Before(value = "execution(* com.evan.spring5.autoano.User.add(..))")
public void before() {
System.out.println("before...");
}
//最终通知:在被代理的目标方法(不管方法是否有异常都执行)最终结束后执行(盖棺定论)
@After(value = "execution(* com.evan.spring5.autoano.User.add(..))")
public void after() {
System.out.println("after...");
}
//后置通知(返回通知):在被代理的目标方法(方法有异常不执行)成功结束后执行(寿终正寝)
@AfterReturning(value = "execution(* com.evan.spring5.autoano.User.add(..))")
public void afterReturning() {
System.out.println("AfterReturning...");
}
//异常通知:被代理的目标方法异常结束后执行(死于非命)
@AfterThrowing(value = "execution(* com.evan.spring5.autoano.User.add(..))")
public void afterThrowing() {
System.out.println("AfterThrowing...");
}
//环绕通知:在被代理的目标方法前后执行(如果方法有异常,后面的增强操作不执行)
@Around(value = "execution(* com.evan.spring5.autoano.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前...");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后...");
}
}
3、创建配置类
@Configurable //表示该类是配置类
@ComponentScan(basePackages = {"com.evan.spring5"}) //开启组件扫描
@EnableAspectJAutoProxy //开启Aspect生成代理对象
public class MyConfig {
//创建User对象注入到sping容器
@Bean
public User user() {
return new User();
}
}
- 测试
@Test
public void test2() {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean("user", User.class);
user.add();
}
- 测试结果
当被代理目标方法出现异常时,会执行异常通知同时环绕通知被增强方法执行之前到最终通知结束;同时后置通知不会被执行。
当被代理目标方法没有异常时,会执行除异常通知的所有通知。