Spring详解(七)----AspectJ 实现AOP

2024-08-29 13:08

本文主要是介绍Spring详解(七)----AspectJ 实现AOP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文网址:https://www.cnblogs.com/ysocean/p/7507993.html

AspectJ 实现AOP
目录
1、什么是 AspectJ?
2、切入点表达式
2、Aspect 通知类型
3、AOP具体实例
4、测试异常通知
5、测试环绕通知


上一篇博客我们引出了 AOP 的概念,以及 AOP 的具体实现方式。但是为什么要这样实现?以及提出的切入点表达式到底该怎么理解?
  这篇博客我们通过对 AspectJ 框架的介绍来详细了解。

1、什么是 AspectJ?
  AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,也可以说 AspectJ 是一个基于 Java 语言的 AOP 框架。通常我们在使用 Spring AOP 的时候,都会导入 AspectJ 的相关 jar 包。
在这里插入图片描述

在 spring2.0以后,spring新增了对AspectJ 切点表达式的支持;Aspect1.5新增注解功能,通过 JDK5的注解技术,能直接在类中定义切面;新版本的 spring 框架,也都建议使用 AspectJ 来实现 AOP。所以说在 spring AOP 的核心包 Spring-aop-3.2.jar 里面也有对 AspectJ 的支持。

2、切入点表达式
  上一篇博客中,我们在spring配置文件中配置如下:

<aop:pointcut expression=“execution(* com.ys.aop..(…))” id=“myPointCut”/>
  那么它表达的意思是 返回值任意,包名为 com.ys.aop 下的任意类名中的任意方法名,参数任意。那么这到底是什么意思呢?
  首先 execution 是 AspectJ 框架定义的一个切入点函数,其语法形式如下:
execution(modifiers-pattern? ref-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)类修饰符 返回值 方法所在的包 方法名 方法抛出的异常
  简单点来说就是:
1 语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
  具体解释我们用下面一张思维导图来看:
在这里插入图片描述

注意:如果切入点表达式有多个不同目录呢? 可以通过 || 来表示或的关系。  
<aop:pointcut expression=“execution(* com.ys.Service1.(…)) || execution(* com.ys.Service2.(…))” id=“myPointCut”/>
  表示匹配 com.ys包下的,以 Service1结尾或者以Service2结尾的类的任意方法。
  
  AOP 切入点表达式支持多种形式的定义规则:
1、execution:匹配方法的执行(常用)
execution(public .(…))
2.within:匹配包或子包中的方法(了解)
within(com.ys.aop…*)
3.this:匹配实现接口的代理对象中的方法(了解)
this(com.ys.aop.user.UserDAO)
4.target:匹配实现接口的目标对象中的方法(了解)
target(com.ys.aop.user.UserDAO)
5.args:匹配参数格式符合标准的方法(了解)
args(int,int)6.bean(id)
6对指定的bean所有的方法(了解)
bean(‘userServiceId’)

2、Aspect 通知类型
Aspect 通知类型,定义了类型名称以及方法格式。类型如下:
before:前置通知(应用:各种校验)
在方法执行前执行,如果通知抛出异常,阻止方法运行afterReturning:
后置通知(应用:常规数据处理)
方法正常返回后执行,如果方法中抛出异常,通知无法执行 必须在方法执行后才执行,所以可以获得方法的返回值。
around:环绕通知(应用:十分强大,可以做任何事情) 方法执行前后分别执行,可以阻止方法的执行 必须手动执行目标方法
afterThrowing:抛出异常通知(应用:包装异常信息) 方法抛出异常后执行,如果方法没有抛出异常,无法执行
after:最终通知(应用:清理现场) 方法执行完毕后执行,无论方法中是否出现异常
  这里最重要的是around,环绕通知,它可以代替上面的任意通知。
  在程序中表示的意思如下:
123456789 try{ //前置:before //手动执行目标方法 //后置:afterRetruning} catch(){ //抛出异常 afterThrowing} finally{ //最终 after}
  对应的 jar 包如下:
  在这里插入图片描述

我们可以查看源码:
  
在这里插入图片描述
在这里插入图片描述
3、AOP具体实例
  ①、创建接口
package com.ys.aop; public interface UserService {
//添加 user
public void addUser();
//删除 user
public void deleteUser();}
  ②、创建实现类
package com.ys.aop; public class UserServiceImpl implements UserService{
@Override
public void addUser() {
System.out.println(“增加 User”);
}
@Override
public void deleteUser() {
System.out.println(“删除 User”);
}
}
  ③、创建切面类(包含各种通知)  
package com.ys.aop; import org.aspectj.lang.JoinPoint; public class MyAspect {
/** * JoinPoint 能获取目标方法的一些基本信息

  • @param joinPoint
  • */
  • public void myBefore(JoinPoint joinPoint){
  • 	System.out.println("前置通知 : " + joinPoint.getSignature().getName());    
    
  • }
  • public void myAfterReturning(JoinPoint joinPoint,Object ret){
  • 	System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);    
    
  • }
  • public void myAfter(){ System.out.println(“最终通知”);
  • }
    }
      ④、创建spring配置文件applicationContext.xml
      我们首先测试前置通知、后置通知、最终通知

aop:config <aop:aspect ref=“myAspect”>

<aop:pointcut expression=“execution(* com.ys.aop..(…))” id=“myPointCut”/>

<aop:before method="myBefore" pointcut-ref="myPointCut"/>                          
<!-- 3.2后置通知  ,目标方法后执行,获得返回值                
<aop:after-returning method="" pointcut-ref="" returning=""/>                   returning 通知方法第二个参数的名称                通知方法格式:public void myAfterReturning(JoinPoint joinPoint,Object ret){                    参数1:连接点描述                    参数2:类型Object,参数名 returning="ret" 配置的        -->        <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />                     <!-- 3.3 最终通知 -->                <aop:after method="myAfter" pointcut-ref="myPointCut"/>                       </aop:aspect>    </aop:config>
  ⑤、测试 @Test public void testAop(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService useService = (UserService) context.getBean("userService"); useService.addUser(); }   控制台打印:   ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190802082245821.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTMxMzE3MTY=,size_16,color_FFFFFF,t_70)

注意,后置通知的返回值为 null,是因为我们的目标方法 addUser() 没有返回值。如果有返回值,这里就是addUser() 的返回值。

4、测试异常通知
  目标接口保持不变,目标类我们手动引入异常:
public void addUser() {
int i = 1/0;
//显然这里会抛出除数不能为 0
System.out.println(“增加 User”);
}
  接着配置切面:MyAspect.java
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("抛出异常通知 : " + e.getMessage());
}
  接着在 applicationContext.xml 中配置如下:

<aop:after-throwing method=“myAfterThrowing” pointcut-ref=“myPointCut” throwing=“e”/>
  测试:
@Test
public void testAop(){
String str = “com/ys/execption/applicationContext.xml”;
ApplicationContext context = new ClassPathXmlApplicationContext(str);
UserService useService = (UserService) context.getBean(“userService”); useService.addUser();
}
  控制台打印:
  在这里插入图片描述

5、测试环绕通知
  目标接口和目标类保持不变,切面MyAspect 修改如下:
public class MyAspect {
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println(“前置通知”);
//手动执行目标方法
Object obj = joinPoint.proceed();
System.out.println(“后置通知”);
return obj;
}
}
  applicationContext.xml 配置如下:

<aop:around method=“myAround” pointcut-ref=“myPointCut”/>
  测试:
@Test
public void testAop(){
String str = “com/ys/around/applicationContext.xml”;
ApplicationContext context = new ClassPathXmlApplicationContext(str);
UserService useService = (UserService) context.getBean(“userService”); useService.addUser();
}
  打印结果:
  在这里插入图片描述

那么至此,通过 xml 配置的方式我们讲解了Spring AOP 的配置。下一章将通过注解的方式来实现。

这篇关于Spring详解(七)----AspectJ 实现AOP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1117943

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof