AOP思想
什么是AOP
是一种设计思想,是oop一种补充;AOP采取横向收取机制,取代了传统纵向继承体系重复性代码。
面向切面编程,传统的oop开发中的代码逻辑是自上而下的,这些自上而下的过程中会产生一些重复的横切性问题,这些横切的问题和我们主要的业务逻辑关系不大,会散落在代码的各个功能地方,维护麻烦;AOP是编程思想就是把业务逻辑和横切问题进行分离,从而达到解耦的目的,提高代码的重用性和开发效率。
AOP应用场景
- 日志记录
- 权限管理
- 事务管理
- 性能监控
- 缓存优化(第一次访问,查询数据库,放入缓存,第二次以后访问从缓存返回)
AOP相关术语
-
连接点-Joinpoint:其实就是业务方法(目标对象中的方法);Spring中只支持方法类型的连接点
-
切入点-Pointcut:如果通知定义了切面的“什么”和“何时”,那么切点定义了“何处”;对joinpoint进行拦截的定义
-
通知-Advice:定义了切面是什么,以及何时使用
分为:前置通知、后置通知、返回通知、异常通知、环绕通知
-
引介-Introduction:允许我们向现有的类添加新的方法或属性
-
目标对象-target:被切入的对象,代理的目标对象
-
织入-Weaving:把切面应用到目标对象并创建新的代理对象的过程
-
代理-Proxy:一个类被AOP织入增强后,产生的一个结果代理类
-
切面-Aspect:通知和切点的结合
AOP底层实现的原理
动态代理
spring aop实现原理
如果组件定义了接口,则使用jdk创建动态代理;如果没有接口,则使用CGlib创建动态代理
SpringAOP案例
- 将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
- 在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
- 开启基于注解的aop模式;@EnableAspectJAutoProxy
maven依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>XXXX</version>
</dependency>
业务类(目标对象)
public class MathCalculator {
public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
}
}
切面类(切面)
@Aspect
public class LogAspects {
//抽取公共的切入点表达式
//1、本类引用
//2、其他的切面引用
@Pointcut("execution(public int com.dwb.aop.MathCalculator.*(..))")
public void pointCut(){};
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
}
@After("com.dwb.aop.LogAspects.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
说明:JoinPoint一定位于通知形参的第一个
目标对象的形参、异常、返回值等通过连接点获取 joinpoint获取
测试类
//该注解很重要
@EnableAspectJAutoProxy
@Configuration
public class Client {
//业务逻辑类加入容器中
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
AnnotationConfigApplicationContext applicationContext
= new AnnotationConfigApplicationContext(Client.class);
//1、不要自己创建对象
// MathCalculator mathCalculator = new MathCalculator();
// mathCalculator.div(1, 1);
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
mathCalculator.div(8, 2);
applicationContext.close();
}
说明:Spring中,aop,对象必须通过ioc创建,自己new出来,不会执行切面不会生效;因为aop底层是动态代理实现
输出结果:
div运行。。。@Before:参数列表是:{[8, 2]}
MathCalculator...div...
div结束。。。@After
div正常返回。。。@AfterReturning:运行结果:{4}
网友评论