目录
一.Aop介绍,以及作用范围,和其专业名词的解释
1.什么是Aop?
2.Aop中的作用范围,以及实际在企业中的开发背景
2.1作用范围
2.2在企业开发的作用
3.Aop 在使用中必有名词
4.spring中Aop的特点
二.实际使用场景5大通知(这里小编以书籍管理系统为例)
实例展示
1.前置通知
定义:
编辑
通过建立一个接口来模拟方法
建立接口后实现方法
实现前置通知方法
打印结果 编辑
2.后置通知
定义:
实现后置通知方法
打印结果
3. 环绕通知
定义:
实现环绕通知方法
打印结果 编辑
4.异常通知
定义:
5.过滤通知
定义:
Java Spring中的AOP(面向切面编程)是一种编程范式,用于通过将与核心业务逻辑无关的横切关注点(如日志记录、性能统计、安全控制等)与核心业务逻辑进行分离,从而提高代码的可维护性和可重用性。
在Java Spring中,AOP通过切面(Aspect)来定义和管理横切关注点。一个切面是由切点(Pointcut)和通知(Advice)组成的。切点定义了在哪些连接点(Joinpoint)上进行横切,通知定义了在连接点上实际执行的逻辑。
切点定义了在连接点上选择哪些具体的执行点进行横切。它可以通过表达式或注解等方式指定。例如,可以使用表达式语言来选择所有的Service层方法作为切点。
通知定义了在连接点上执行的具体逻辑。在Java Spring中,常见的通知类型包括前置通知(Before)、后置通知(After)、返回通知(After-returning)和异常通知(After-throwing)等。
通过使用AOP,我们可以将与核心业务逻辑无关的横切关注点抽离出来,集中进行管理和维护。这样可以使核心业务逻辑更加清晰,避免代码重复,提高代码的可维护性和可重用性。
在Java Spring框架中,AOP的实现使用了动态代理和元数据两种方式。动态代理可以在运行时动态地生成代理对象,实现对连接点的拦截和处理。元数据则是通过配置文件或注解等方式来定义切面和切点的规则和行为。
其关系图如下
应用于各种类型的应用程序和业务领域
在实际的企业开发中,AOP常用于大型应用程序和分布式系统中。它可以提供跨模块和跨层的横切功能,帮助解决模块之间的耦合性和复杂性问题。通过将横切关注点的代码抽离到切面中,可以提高代码的可维护性和可重用性,减少重复代码的编写,提高开发效率
1. 事务管理:AOP可以通过在方法调用前后进行事务的开启和提交/回滚,简化了事务管理的代码和配置。它可以将事务管理关注点从业务逻辑中抽离出来,使开发者能够专注于业务逻辑的实现,提高了事务管理的灵活性和可维护性。
2. 安全控制:AOP可以在方法调用前进行权限校验和身份认证,实现安全控制的功能。通过将安全控制的逻辑与业务逻辑分离,可以确保安全控制的一致性和可扩展性。
3. 日志记录:AOP可以在方法调用前后进行日志记录,帮助开发者追踪和调试代码。它可以通过在切面中插入日志记录的逻辑,实现日志记录的统一管理,避免了在多个方法中重复编写日志记录代码的问题。
4. 性能统计:AOP可以监控方法的执行时间和资源消耗,实现性能统计的功能。通过将性能统计的逻辑与业务逻辑分离,可以更好地了解和优化系统的性能。
5. 异常处理:AOP可以在方法调用发生异常时进行异常处理,例如记录日志、发送警报等。它可以集中管理异常处理的逻辑,提高系统的健壮性和可靠性。
在企业开发中,AOP通常与其他技术和框架一起使用,例如Spring框架、Hibernate框架、Spring MVC框架等。它可以与这些框架无缝集成,共同实现业务逻辑和非功能性需求的开发。
连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
目标(Target):被通知(被代理)的对象
通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)
代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),请注意:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的
切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点。
(也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)
适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)
解决的问题:解决了需求的改变,造成了原有没必要改变的代码,需要去改变它;
比如:书籍的增删改,本身只需要完成增删改的功能即可,这是如果需要添加日志功能,那么需要在原有的代码基础上,去修改添加日志功能,受牵连的方法就三个(add/edit/del)了;
实在不能够理解小编举这样一个例子:比如说明星和经纪人! 明星就是目标,给明星找电影拍,经纪人就是通知。经纪人有了安排,明星和经纪人一起就是代理!
用于在目标方法执行前执行一些额外的逻辑。具体来说,前置通知会在目标方法执行之前被触发,它可以用来进行一些准备工作、参数校验、日志记录等操作
package com.zking.aop.biz;
public interface IBookBiz {
// 购书
public boolean buy(String userName, String bookName, Double price);
// 发表书评
public void comment(String userName, String comments);
}
通过控制台的输出方式模拟购书,通过控制台的输出方式模拟发表书评
package com.zking.aop.biz.impl;
import com.zking.aop.biz.IBookBiz;
import com.zking.aop.exception.PriceException;
public class BookBizImpl implements IBookBiz {
public BookBizImpl() {
super();
}
public boolean buy(String userName, String bookName, Double price) {
// 通过控制台的输出方式模拟购书
if (null == price || price <= 0) {
throw new PriceException("book price exception");
}
System.out.println(userName + " buy " + bookName + ", spend " + price);
return true;
}
public void comment(String userName, String comments) {
// 通过控制台的输出方式模拟发表书评
System.out.println(userName + " say:" + comments);
}
}
在这里,可以获取到目标类的全路径及方法及方法参数,然后就可以将他们写到日志表里去
package com.zking.aop.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* 买书、评论前加系统日志
* @author Administrator
*
*/
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
//在这里,可以获取到目标类的全路径及方法及方法参数,然后就可以将他们写到日志表里去
String target = arg2.getClass().getName();
String methodName = arg0.getName();
String args = Arrays.toString(arg1);
System.out.println("【前置通知:系统日志】:"+target+"."+methodName+"("+args+")被调用了");
}
}
后置通知(After Advice):在一个连接点完成之后(例如,一个方法执行之后)执行的通知。无论连接点是否成功完成,后置通知都会执行。
package com.zking.aop.advice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* 买书返利
* @author Administrator
*
*/
public class MyAfterReturningAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
String target = arg3.getClass().getName();
String methodName = arg1.getName();
String args = Arrays.toString(arg2);
System.out.println("【后置通知:买书返利】:"+target+"."+methodName+"("+args+")被调用了,"+"该方法被调用后的返回值为:"+arg0);
}
}
环绕通知(Around Advice):环绕通知围绕在一个连接点的整个调用过程中执行。可以理解h
package com.zking.aop.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.util.Arrays;
/**
* 环绕通知
* 包含了前置和后置通知
*
* @author Administrator
*
*/
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
String target = arg0.getThis().getClass().getName();
String methodName = arg0.getMethod().getName();
String args = Arrays.toString(arg0.getArguments());
System.out.println("【环绕通知调用前:】:"+target+"."+methodName+"("+args+")被调用了");
// arg0.proceed()就是目标对象的方法
Object proceed = arg0.proceed();
System.out.println("【环绕通知调用后:】:该方法被调用后的返回值为:"+proceed);
return proceed;
}
}
异常通知(After Throwing Advice):在方法抛出异常后执行的通知。可以用于捕获方法抛出的特定异常,并采取相应的处理措施。
过滤通知(Before Advice):在一个连接点之前执行的通知。可以在方法执行前做一些准备工作,如参数检查、权限验证等。