1,AOP实现的项目需求背景
背景: AOP 可以在不改变原有逻辑的情况下做一个扩展,因为做因为做定制化开发的话,不能拿到源码,也就不能直接修改源码,只能在源码及上做一个扩展;这个时候如果需要增强方法的功能,或者扩展一些业务功能;就可以使用到AOP做一个切面编程;
2,定义切点
//只用这个注解 让Spring 去管理我们的扩展类的bean
@Component
// 该注解表示这个类要是用AOP
@Aspect
public class AspectsDemo {
// 定义指定要对那个类的那个方法做一个切面,这里是个绝对路径
// * 代表 返回值类型不限
// .. 代表 参数不限
// 这个路径也可以称为切点
@Pointcut("execution(public * com.paraview.infini.gateway.manager.impl.GwAppManagerImpl.query(..))")
public void pointCat(){};
// 应用上面定义的绝对路径的切点
@Before("pointCat()")
public void logStart(){
System.out.println("@Before方法运行之前");
}
// 无论正常还是结束 目标方法执行之后执行
@After("pointCat()")
public void logEnd(){
System.out.println("@After目标方法运行结束啦");
}
@AfterReturning("pointCat()")
public void logReturn(){
System.out.println("@AfterReturning方法正常返回");
}
// 当目标方法执行有异常的时候被执行
@AfterThrowing("pointCat()")
public void logExcrption(){
System.out.println("@AfterThrowing方法运行异常");
}
@Around("pointCat()")
public Object Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 这里相当于做了一个反射 去执行
System.out.println("@Around执行目标方法之前=======");
Object proceed = proceedingJoinPoint.proceed();
System.out.println("@Around执行目标方法之后=======");
return proceed;
}
}
3,执行切点目标方法方法测试
public * com.paraview.infini.gateway.manager.impl.GwAppManagerImpl.query(..)
[2022-11-06 10:39:25.998] [] [ERROR] - 请求头中clusterId为空
@Around执行目标方法之前=======
@Before方法运行之前
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b1c0169] was not registered for synchronization because synchronization is not active
[2022-11-06 10:39:29.590] [] [ INFO] - {dataSource-1} inited
JDBC Connection [org.postgresql.jdbc.PgConnection@2a9eb39d] will not be managed by Spring
==> Preparing: SELECT count(0) FROM "gw_app" WHERE 1 = 1 AND "custom_cluster_id" = ? AND "is_delete" = false
==> Parameters: null
<== Columns: count
<== Row: 0
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b1c0169]
@AfterReturning正常返回
@After目标方法运行结束啦
@Around执行目标方法之后=======
小结:
执行顺序:
1,先是执行@Around 的前置通知
2,再执行@Before 的前置通知
3,再执行 我们的目标切点方法
4,在执行@AfterReturning 目标方法正常返回之后的方法
5,再执行@After 的后置通知
6,再执行 @Around 的后置通知;
注解的解释;
@Before : 可以看做为在执行目标方法之前我们把他拦截下来, 可以做一些增强,或者日志,先执行我们的通知方法,再执行目标方法;可更具实际情况,在前置通知 编写自己的业务代码 ;
@After: 其实就是目标方法执行完之后;就执行我们的后置通知方法;例如做日志答应,做一些功能增加功能;
@AfterReturning : 在目标方法执行结束正常返回的时候就会执行;
@AfterThrowing : 当目标方法执行异常之后改方法就会被执行;
@Around : 其实就是一个环绕通知,从代码中也可以看到 就是一个前置后置组合在一个的通知;
业务无背景解决:
公司实际需求:业务是一个数据同步到另一个服务的需求; 源码不能改变,当修改另一个服务的数据时同步到另一个服务;
可以使用AOP:
1,做一个前置通知;先同步到另一个服务,然后在修改本服务的;
2,也可以做一个后置通知: 先修改本服务的,然后在同步到另一个服务上;
非AOP解决方案:
3, 可以做一个继承 重写原来的方法,在执行父类方法执行做一个同步,或者执行方法之后做一个同步;和AOP类似