关于springAOP,面向切面编程

xiaoxiao2021-02-28  55

AOP面向方面/面向切面编程 AOP将分散在系统中的功能块放到一个地方- 切面 可以声明式的定义何时何地应用这些功能,而不是在需要新功能的地方修改代码 好处 每个业务逻辑放在一个地方,不是分散到代码各个角落。业务模块只包含核心功能,辅助功能转到切面中,使其更加清晰。 关注的是共同处理。通过spring配置把某个作用应用到多个点上。提高灵活性 重要术语 切面(Aspect):就是你要实现的交叉功能---共通业务处理可以被切入到多个目标对象。并且多次使用 连接点(Joinpoint):应用程序执行过程中插入切面的地点 通知(Advice):通知切面的实际实现    切入点(Pointcut):定义通知应用在哪些连接点---连接点的集和 目标对象(Target Object):被通知的对象,也就是目标对象 代理(Proxy):将通知应用到目标对象后创建的对象---AOP中容器返回的对象是代理对象。用户在使用的时候,由代理对象调用切面组件和目标对象的功能 织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程 我们进入案例01---需要引入额外jar包,这点要注意通过实验慢慢引入 1:编写dao类用来进行正常的增删改查 service 2:编写切面用于共同业务处理---记录日志 3:编写我们的xml文件 <aop:config> <aop:pointcut id="userPointCut" expression="execution(* com.wode.service.UserService.*(..))" /> <aop:aspect id="logAspect"  ref="userLogger"> <aop:before method="testLogger" pointcut-ref="userPointCut"></aop:before> </aop:aspect> </aop:config> 重要概念: <aop:config>---指的是需要进行AOP配置了 <aop:pointcut id="userPointCut" expression="execution(* com.wode.service.UserService.*(..))" />----设置切面 expression这个用于设置规则 execution--具体规则类容 我们现在设置的就是不用管返回值+包类.*(所有方法)不限定参数类型 我们可以做这样的实验 01:expression="execution(* com.wode.service.UserService.delete(..))" 02:expression="execution(void com.wode.service.UserService.*(..))" /> 看看有什么不一样 这里是使用的切入点表达式我们可以看一下规则-参考网站可以参照一下表达式.txt从网上下载的 注意我们还可以使用一种within的方式 within用于匹配指定类型内的方法执行--这里和上边对应上边用于指定方法(更灵活) 例如<aop:pointcut id="userPointCut" expression="within(com.wode.service.UserService)" />和上边的就一个意思 within(com.wode.service.*)---包下边所有的方法 within(com.wode.service..*)这样写的话就包括了子包 <aop:aspect>--用于配置切面 id---起id名称 ref--指向我们的切面文件 <aop:before method="testLogger" pointcut-ref="userPointCut"></aop:before>--指定方法以及在什么时候发生以及他的切入点 注意除了aop:before是指在之前发生,这里总共有这么多类型可以让我们选择 默认提供通知类型 <aop:before>---前置通知 <aop:after-returning>方法调用之后,但是如果有异常将不通知 <aop:after>最终通知 <after-throwing>方法调用发生异常之后 <aop-around>环绕通知,也就是方法之前和之后 分步骤测试 演示前置和后置通知 这里需要注意的是Around他相当于之前所有返回的结合体,需要注意的是它的返回值异常-----方法返回值和我们切面的返回值 但是它非常好用,我们可以通过它通过ProceedingJoinPoint--来获取方法名、类名等等东西 演示ProceedingJoinPoint 案例 Object obj=pjo.proceed();  System.out.println(obj); System.out.println(pjo.getTarget()); System.out.println(pjo.getArgs()[0]); System.out.println(pjo.getSignature().getName()); System.out.println(pjo.getTarget().getClass().getName()); 除了他之外,我们的后置通知也能获取方法的返回值需要做的 不过需要我们做的是 1:在xml中做改变 <aop:after-returning method="testLoggerafetr" returning="test" pointcut-ref="userPointCut"></aop:after-returning> 2:在切面中做改变 public void testLoggerafetr(int test) throws Throwable{ System.out.println("后置记录日志"); System.out.println(test); } 最后我们来测试异常通知aop:after-throwing 理所当然的,我们也可以在切面中获取这个异常 <aop:after-throwing method="testLoggerException" throwing="e" pointcut-ref="userPointCut"></aop:after-throwing> public void testLoggerException(Exception e) throws Throwable{ System.out.println("异常记录日志"+e); } 最后:福利 1:删除所有在xml中关于AOP的东西 2:加入这样一句话 <aop:aspectj-autoproxy /> 3:使用注解 @Component("userLogger") @Aspect 4:定义切入点: @Pointcut("within(com.wode.service.UserService)") public void pointCut(){} 5:设置 @Before("pointCut()") public void testLogger() throws Throwable{ System.out.println("前置记录日志"); } 切入点表达式第二种方式: @Pointcut("execution(* com.wode.service.UserService.*(..))") public void pointCut(){} 我们来看特殊的 @Around("pointCut()") public int testLogger(ProceedingJoinPoint pjo) throws Throwable{ System.out.println("前置记录日志"); Object obj=pjo.proceed(); System.out.println(obj); System.out.println(pjo.getTarget()); System.out.println(pjo.getArgs()[0]); System.out.println(pjo.getSignature().getName()); System.out.println(pjo.getTarget().getClass().getName()); return (int) obj; } 这里还是需要注意返回值的问题 异常通知 @AfterThrowing(pointcut="pointCut()",throwing="e") public int testLogger(Exception e) throws Throwable{ System.out.println("前置记录日志"+e); return  1; } 当然别的通知中我们需要获得参数啊什么的就可以这么做 @Before("pointCut()")  public int testLogger(JoinPoint jpt) throws Throwable{ System.out.println("前置记录日志"); System.out.println(jpt.getTarget()); return 1;

}

转载请注明原文地址: https://www.6miu.com/read-39003.html

最新回复(0)