首页 > 编程语言 >@Aspect 注解使用详解

@Aspect 注解使用详解

时间:2022-11-24 19:40:17浏览次数:60  
标签:lang String point annotation 详解 Aspect import 注解 public


AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是​​OOP​​​的延续,是软件开发中的一个热点,也是​​Spring​​​框架中的一个重要内容,是​​函数式编程​​​的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的​​耦合度​​降低,提高程序的可重用性,同时提高了开发的效率。

在spring AOP中业务逻辑仅仅只关注业务本身,将日志记录,性能统计,安全控制,事务处理,​​异常处理​​等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

相关注解介绍:

  1. @Aspect:作用是把当前类标识为一个切面供容器读取
  2. @Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
  3. @Around:环绕增强,相当于MethodInterceptor
  4. @AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
  5. @Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
  6. @AfterThrowing:异常抛出增强,相当于ThrowsAdvice
package com.aspectj.test.advice;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AdviceTest {
@Around("execution(* com.abc.service.*.many*(..))")
public Object process(ProceedingJoinPoint point) throws Throwable {
System.out.println("@Around:执行目标方法之前...");
//访问目标方法的参数:
Object[] args = point.getArgs();
if (args != null && args.length > 0 && args[0].getClass() == String.class) {
args[0] = "改变后的参数1";
}
//用改变后的参数执行目标方法
Object returnValue = point.proceed(args);
System.out.println("@Around:执行目标方法之后...");
System.out.println("@Around:被织入的目标对象为:" + point.getTarget());
return "原返回值:" + returnValue + ",这是返回结果的后缀";
}

@Before("execution(* com.abc.service.*.many*(..))")
public void permissionCheck(JoinPoint point) {
System.out.println("@Before:模拟权限检查...");
System.out.println("@Before:目标方法为:" +
point.getSignature().getDeclaringTypeName() +
"." + point.getSignature().getName());
System.out.println("@Before:参数为:" + Arrays.toString(point.getArgs()));
System.out.println("@Before:被织入的目标对象为:" + point.getTarget());
}

@AfterReturning(pointcut="execution(* com.abc.service.*.many*(..))",
returning="returnValue")
public void log(JoinPoint point, Object returnValue) {
System.out.println("@AfterReturning:模拟日志记录功能...");
System.out.println("@AfterReturning:目标方法为:" +
point.getSignature().getDeclaringTypeName() +
"." + point.getSignature().getName());
System.out.println("@AfterReturning:参数为:" +
Arrays.toString(point.getArgs()));
System.out.println("@AfterReturning:返回值为:" + returnValue);
System.out.println("@AfterReturning:被织入的目标对象为:" + point.getTarget());

}

@After("execution(* com.abc.service.*.many*(..))")
public void releaseResource(JoinPoint point) {
System.out.println("@After:模拟释放资源...");
System.out.println("@After:目标方法为:" +
point.getSignature().getDeclaringTypeName() +
"." + point.getSignature().getName());
System.out.println("@After:参数为:" + Arrays.toString(point.getArgs()));
System.out.println("@After:被织入的目标对象为:" + point.getTarget());
}
}

使用annotation代码:

//注解实体类
package com.trip.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface SMSAndMailSender {
/*短信模板String格式化串*/
String value() default "";

String smsContent() default "";

String mailContent() default "";
/*是否激活发送功能*/
boolean isActive() default true;
/*主题*/
String subject() default "";
}



//切面类
@Aspect
@Component("smsAndMailSenderMonitor")
public class SMSAndMailSenderMonitor {

private Logger logger = LoggerFactory.getLogger(SMSAndMailSenderMonitor.class);


/**
* 在所有标记了@SMSAndMailSender的方法中切入
* @param joinPoint
* @param result
*/
@AfterReturning(value="@annotation(com.trip.demo.SMSAndMailSender)", returning="result")//有注解标记的方法,执行该后置返回
public void afterReturning(JoinPoint joinPoint , Object result//注解标注的方法返回值) {
MethodSignature ms = (MethodSignature) joinPoint.getSignature();
Method method = ms.getMethod();
boolean active = method.getAnnotation(SMSAndMailSender.class).isActive();
if (!active) {
return;
}
String smsContent = method.getAnnotation(SMSAndMailSender.class).smsContent();
String mailContent = method.getAnnotation(SMSAndMailSender.class).mailContent();
String subject = method.getAnnotation(SMSAndMailSender.class).subject();

}



/**
* 在抛出异常时使用
* @param joinPoint
* @param ex
*/
@AfterThrowing(value="@annotation(com.trip.order.monitor.SMSAndMailSender)",throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex//注解标注的方法抛出的异常) {
MethodSignature ms = (MethodSignature) joinPoint.getSignature();
Method method = ms.getMethod();
String subject = method.getAnnotation(SMSAndMailSender.class).subject();

}

}


//实体类中使用该注解标注方法
@Service("testService ")
public class TestService {


@Override
@SMSAndMailSender(smsContent = "MODEL_SUBMIT_SMS", mailContent =
"MODEL_SUPPLIER_EMAIL", subject = "MODEL_SUBJECT_EMAIL")
public String test(String param) {
return "success";
}

注意,记得在配置文件中加上:

<aop:aspectj-autoproxy proxy-target-class="true"/>
package com.ruoyi.framework.aspectj;

import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;

/**
* 数据过滤处理
*
* @author ruoyi
*/
@Aspect
@Component
public class DataScopeAspect
{
/**
* 全部数据权限
*/
public static final String DATA_SCOPE_ALL = "1";

/**
* 自定数据权限
*/
public static final String DATA_SCOPE_CUSTOM = "2";

/**
* 部门数据权限
*/
public static final String DATA_SCOPE_DEPT = "3";

/**
* 部门及以下数据权限
*/
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";

/**
* 仅本人数据权限
*/
public static final String DATA_SCOPE_SELF = "5";

/**
* 数据权限过滤关键字
*/
public static final String DATA_SCOPE = "dataScope";

// 配置织入点
@Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)")
public void dataScopePointCut()
{
}

@Before("dataScopePointCut()")
public void doBefore(JoinPoint point) throws Throwable
{
handleDataScope(point);
}

protected void handleDataScope(final JoinPoint joinPoint)
{
// 获得注解
DataScope controllerDataScope = getAnnotationLog(joinPoint);
if (controllerDataScope == null)
{
return;
}
// 获取当前的用户
SysUser currentUser = ShiroUtils.getSysUser();
if (currentUser != null)
{
// 如果是超级管理员,则不过滤数据
if (!currentUser.isAdmin())
{
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias());
}
}
}

/**
* 数据范围过滤
*
* @param joinPoint 切点
* @param user 用户
* @param deptAlias 部门别名
* @param userAlias 用户别名
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
{
StringBuilder sqlString = new StringBuilder();

for (SysRole role : user.getRoles())
{
String dataScope = role.getDataScope();
if (DATA_SCOPE_ALL.equals(dataScope))
{
sqlString = new StringBuilder();
break;
}
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
{
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
role.getRoleId()));
}
else if (DATA_SCOPE_DEPT.equals(dataScope))
{
sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
}
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
{
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or ancestors like '%{}%'",
deptAlias, user.getDeptId(), user.getDeptId()));
}
else if (DATA_SCOPE_SELF.equals(dataScope))
{
if (StringUtils.isNotBlank(userAlias))
{
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
}
else
{
// 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" OR 1=0 ");
}
}
}

if (StringUtils.isNotBlank(sqlString.toString()))
{
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
}
}
}

/**
* 是否存在注解,如果存在就获取
*/
private DataScope getAnnotationLog(JoinPoint joinPoint)
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();

if (method != null)
{
return method.getAnnotation(DataScope.class);
}
return null;
}
}

 

标签:lang,String,point,annotation,详解,Aspect,import,注解,public
From: https://blog.51cto.com/u_15890333/5884595

相关文章

  • golang 反向代理 Gin框架反向代理详解
    前言想用gin框架做一个反向代理服务,搜索了一圈,全是只讲解些皮毛的帖子,今天我就总结一下gin做反向代理的详细操作和原理正文开始之前我们先了解一些前置知识gin的通配符......
  • 网络性能评估工具Iperf详解
     一、网络性能评估工具Iperf网络性能评估主要是监测网络带宽的使用率,将网络带宽利用最大化是保证网络性能的基础,但是由于网络设计不合理、网络存在安全漏洞等原因,都会导......
  • SD NAND 的 SDIO在STM32上的应用详解(中篇)
    四.SDIO功能框图(重点)SDIO包含2个部分:●SDIO适配器模块:实现所有MMC/SD/SDI/O卡的相关功能,如时钟的产生、命令和数据的传送。●AHB总线接口:操作SDIO适配器模块中的寄存器......
  • VC++模拟键盘输入(keybd_event() 、 PostMessage() /SendMessage()、SendInput())详解
                                           VC++模拟键盘输入找了一周,终于找到模拟键......
  • pat 并查集题目代码详解
    不得不吐槽并查集的题太少了1118:1//一道并查集查询的题目2//需要注意的几个点3//输入的时候在进行合并时,是一个一个输入的,所以需要引入一个变量来存储前一个输......
  • pat 散列题目代码详解
    1002:1//思路很简单,存哈希表直接计算就可以了2//需要注意的几个点3//求最高次数的时候判断当前的系数是否为04//倒着输出的时候注意格式5#include<bits/std......
  • 【Android游戏开发十三】(保存游戏数据 [下文])详解SQLite存储方式,并把SQLite的数据库
    ​​ 李华明Himi ​​​原创,转载务必在明显处注明: 很多童鞋说我的代码运行后,点击home或者back后会程序异常,如果你也这样遇到过,那么你肯定没有仔细读完Himi的博文,第十九......
  • pat dijkstra系列题目代码详解
    1003:1#include<bits/stdc++.h>2usingnamespacestd;3#defineintlonglong4#defineIOSios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);5const......
  • pat list题目代码详解
    1032:1#include<bits/stdc++.h>2usingnamespacestd;3#defineIOSios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);4#defineintlonglong5const......
  • Istio详解
    目录1.前言2.什么是istio?3.什么是servicemesh?4.再来看istio5.istio解决什么问题6.用什么姿势接入istio?7.总结1.前言如果你比较关注新兴技术的话,那么很可能在不同的......