AOP实战分享——简单注解联动和方法前后参数修改

在实战开始之前,先进行简单的配套说明,既然是注释相关,那么肯定要对注释有一定的说明:
对注释有了解的可以直接略过。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Authorize {
	String paramater() default "id"; // 参数名称,默认参数名id
}

上面是一个简单的例子,使用了简单的注释,其中@Target方法用于定义注释使用的位置,上面的ElementType.METHOD对应的是方法,也就是在方法上使用注释,其从名称METHOD可以简单的看出。其余相关方法图示一览:
在这里插入图片描述
@Retention注解用于编译时的预操作,这里我们选择RetentionPolicy.RUNTIME,对应参与JVM运算,可以理解为运行时,以下为源码分类一览:
在这里插入图片描述
@Documented 是javadoc相关,在使用后,根据是否使用注解,来区分是否出来在生成的文档中

以上都是注解的简单使用和说明,理解了上面的说明后,我们来看AOP对注解的切入使用,这种使用可以尽量做到低耦合,甚至无耦合。

@Aspect
@Component
@Slf4j
@Order(3) // 这里定义执行顺序,值越小越先执行,执行可以看成是一个同心圆,around前的先执行,around后的后执行
public class AuthorizeAcpect {

    /**
     * 定义切入点
     */
    @Pointcut("@annotation(xxx.xxx.annotation.Authorize)")
    public void authorize() {
    }

    @Around("authorize()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        String[] parameterNames = methodSignature.getParameterNames();
        
        Authorize annotation = method.getAnnotation(Authorize.class);

        int indexParamater = ArrayUtils.indexOf(parameterNames, annotation.paramater());  // paramater对应参数名,请直接将参数名传入
        Object[] args = point.getArgs();
        Integer id = (Integer) args[indexParamater]; // Id获取Integer写死,毕竟传入的参数类型

        // 处理id如设定id = 6
        Integer refId = 6;
        args[indexParamater] = refId;

        Object object = point.proceed(args); // 执行方法

        // 了解返回值的实体类或者 instanceof
        if (object instanceof Integer) {
            return id; // 返回
        }

        return object;
    }

}
	

@Aspect
@Component
这两个注解对应Spring AOP、Spring Boot,如果你使用的Spring,那么请老老实实地在XML配置AOP

@Order(3) // 用于定义执行顺序,其中越小圈在外面也就越早执行,多个AOP则是一个同心圆,其中圆心是方法执行

MethodSignature methodSignature = (MethodSignature) point.getSignature();
Method method = methodSignature.getMethod();
String[] parameterNames = methodSignature.getParameterNames();
是写死的获取参数列表的方法,同时保证了参数的顺序,因此,可以通过判断参数列表的位置,来判断args[]里面的值的位置

annotation.paramater()为写在注解中的参数名称,这就能通过上面的参数列表,计算出参数所在的位置

int indexParamater = ArrayUtils.indexOf(parameterNames, annotation.paramater()); // 获取参数Id所在位置
计算方法如上,这个ArrayUtils 我看了一下是package org.apache.commons.lang 我觉得这个应该是大家都在使用的工具包就不详谈了

Object[] args = point.getArgs();
此为使AOP内方法进行执行状态,在执行完成后的值则会返回到object,同时这也意味着方法执行后可以进行再次进行修改

if (object instanceof Integer) {
return id; // 返回
}
这里模仿了对参数的修改,当是Integer类型时,直接返回之前获取的修改前的值

这就保证了参数传入Id,id自动转换为6,业务方面用6操作,返回后,6再次转换为原id的Aop处理
这使用了AOP保证了Id的转换在业务中0耦合,当然实际业务肯定更加复杂,这里将复杂的业务进行了简单的替换,在实际业务中当然也可以追求0耦合,但是也要灵活操作,部分时候,可以灵活传入key值,通过key值,较少耦合完成需求

以上是很简单的AOP使用,当然为了保证水平较差的同学也能理解,多废了一些口舌,否则我相信直接贴上代码,说几句使用心得就行了
如果有太啰嗦请进行指正,同时也希望有路过的大佬,有更精巧的心得,一并分享出来,一起讨论,期待和大佬思想和代码层面的交流。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP是Spring框架中的一个重要模块,它提供了面向切面编程(AOP)的支持。AOP是一种编程思想,它可以在不改变原有代码的情况下,通过在程序运行时动态地将代码“织入”到现有代码中,从而实现对原有代码的增强。 Spring AOP提供了基于注解AOP实现,使得开发者可以通过注解的方式来定义切面、切点和通知等相关内容,从而简化了AOP的使用。 下面是一个基于注解AOP实现的例子: 1. 定义切面类 ```java @Aspect @Component public class LogAspect { @Pointcut("@annotation(Log)") public void logPointcut() {} @Before("logPointcut()") public void beforeLog(JoinPoint joinPoint) { // 置通知 System.out.println("执行方法:" + joinPoint.getSignature().getName()); } @AfterReturning("logPointcut()") public void afterLog(JoinPoint joinPoint) { // 后置通知 System.out.println("方法执行完成:" + joinPoint.getSignature().getName()); } @AfterThrowing(pointcut = "logPointcut()", throwing = "ex") public void afterThrowingLog(JoinPoint joinPoint, Exception ex) { // 异常通知 System.out.println("方法执行异常:" + joinPoint.getSignature().getName() + ",异常信息:" + ex.getMessage()); } } ``` 2. 定义业务逻辑类 ```java @Service public class UserService { @Log public void addUser(User user) { // 添加用户 System.out.println("添加用户:" + user.getName()); } @Log public void deleteUser(String userId) { // 删除用户 System.out.println("删除用户:" + userId); throw new RuntimeException("删除用户异常"); } } ``` 3. 在配置文件中开启AOP ```xml <aop:aspectj-autoproxy/> <context:component-scan base-package="com.example"/> ``` 在这个例子中,我们定义了一个切面类LogAspect,其中通过@Aspect注解定义了一个切面,通过@Pointcut注解定义了一个切点,通过@Before、@AfterReturning和@AfterThrowing注解分别定义了置通知、后置通知和异常通知。 在业务逻辑类中,我们通过@Log注解标注了需要增强的方法。 最后,在配置文件中,我们通过<aop:aspectj-autoproxy/>开启了AOP功能,并通过<context:component-scan>扫描了指定包下的所有组件。 这样,当我们调用UserService中的方法时,就会触发LogAspect中定义的通知,从而实现对原有代码的增强。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值