Spring Boot面向切面加注解高级用法

1、注解类

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

@Target({ElementType.METHOD}) //应用于方法上面
@Retention(RetentionPolicy.RUNTIME)//表示在运行时注解任可用
public @interface OperationLogAnno {
    /**
     * 操作位置
     */
    String operatePage() default "";
    /**
     * 操作类型
     */
    String operateType() default "";
    /**
     * 业务域,各自业务自己定义
     */
    String bizType() default "";
}

2、pom 引入面向切面依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

3、切面类切到注解上



import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
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.AfterThrowing;
import org.aspectj.lang.annotation.Around;
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.example.annotation.OperationLogAnno;
import org.springframework.stereotype.Component;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;


@Aspect
@Component
@Slf4j
public class LogAspect  {

    private static final ThreadLocal<String> threadLocal=new ThreadLocal<>();

    //切点
    @Pointcut("@annotation(org.example.annotation.OperationLogAnno)")
    private void cutMethod() {

    }

    //
    @Before("cutMethod()")
    public void before(JoinPoint joinPoint) throws Throwable {

        String uuid = IdUtil.simpleUUID();
        log.info("uuid:"+uuid);
        threadLocal.set(uuid);


        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        log.info("methodName={}", methodName);
        // 反射获取目标类
        Class<?> targetClass = joinPoint.getTarget().getClass();

        Object[] params = joinPoint.getArgs();

        log.info("params={}", params);

        // 拿到方法对应的参数类型
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        // 根据类、方法、参数类型(重载)获取到方法的具体信息
        Method objMethod = targetClass.getMethod(methodName, parameterTypes);

        // 获取方法上声明的注解
        OperationLogAnno anno = objMethod.getDeclaredAnnotation(OperationLogAnno.class);
         if( anno== null ){
             //尝试获取接口上的注解类
             anno = (OperationLogAnno) ((Class) AopUtils.getTargetClass(joinPoint.getTarget()).getGenericInterfaces()[0]).getDeclaredMethod(objMethod.getName(),parameterTypes).getAnnotation(OperationLogAnno.class);
        }

        info(anno);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        String servletPath = request.getServletPath();
        log.info("servletPath:" + servletPath);

        log.info("路径匹配结果" + PatternMatchUtils.simpleMatch("/user/**", servletPath));

        //url
        log.info("url={}", request.getRequestURL());
        //method
        log.info("method={}", request.getMethod());
        //ip
        log.info("ip={}", request.getRemoteAddr());
        //类方法
        log.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        Object[] r = joinPoint.getArgs();
        //参数
        log.info("args={}", r);

    }

    @After(value = "cutMethod()")
    public void after() {
        log.info("after.........");
        log.info("uuid:"+threadLocal.get());
    }

    @AfterReturning(returning = "object", pointcut = "cutMethod()")
    public void doAfterReturning(Object object) {
        log.info("response={}", JSONUtil.toJsonStr(object));
    }

    @AfterThrowing(value="cutMethod()",throwing = "exception")
    public void afterThrowing(Exception exception) {
        System.out.println("afterThrowing.........");
        log.info("exception:",exception);
    }

    @Around(value = "cutMethod()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("doAroundFront");
        Object res = null;
        try {
            res = joinPoint.proceed(joinPoint.getArgs());
        } catch (Throwable e) {
            log.error("切面异常",e);
            throw e;
        }
        //对res修改可以更改返回值
        System.out.println("doAroundBehind");
        return res;
    }



    @SneakyThrows
    private <T extends Annotation>void info(T t) {
        Method[] methods=t.getClass().getDeclaredMethods();
        Map<String,String> map=new HashMap<>();
        for(Method method:methods){
            if(!method.getName().contains("hashCode")&&
                    !method.getName().contains("equals")&&
            !method.getName().contains("toString")&&
                    !method.getName().contains("annotationType")){
                map.put(method.getName(),(String)method.invoke(t));
            }
        }
        log.info("annotation={}", map);
    }



}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更便捷、个性化的教育体验。
### 回答1: 在 Spring Boot 中,可以使用 AOP(面向切面编程)来实现切面环绕。通过使用 AOP,我们可以在应用程序的不同部分添横切关注点,而无需修改这些部分的源代码。 下面是一个示例,展示了如何在 Spring Boot 中使用 AOP 进行切面环绕: 1.首先,我们需要创建一个切面类,该类需要使用 @Aspect 注解进行标注。 ```java @Aspect @Component public class LoggingAspect { } ``` 2.在切面类中,我们需要创建一个环绕通知方法,该方法需要使用 @Around 注解进行标注。 ```java @Around("execution(* com.example.demo.service.*.*(..))") public Object logMethodExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); Object result = joinPoint.proceed(); long endTime = System.currentTimeMillis(); logger.info(joinPoint.getSignature() + " executed in " + (endTime - startTime) + "ms"); return result; } ``` 3.在上面的代码中,我们使用 @Around 注解来标注 logMethodExecutionTime 方法,该方法将会在 service 包下的所有方法执行前后进行环绕通知。在方法中,我们记录了方法的执行时间,并通过日志打印出来。 4.最后,我们需要在 Spring Boot 应用程序启动类上添 @EnableAspectJAutoProxy 注解来启用 AOP 功能。 ```java @SpringBootApplication @EnableAspectJAutoProxy public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 通过上述步骤,我们就可以在 Spring Boot 应用程序中使用 AOP 进行切面环绕了。 ### 回答2: Spring Boot是一个开发框架,可以简化Java开发过程。切面Spring AOP(面向切面编程)的一个重要概念。环绕通知则是AOP中一种通知类型。 在Spring Boot中,我们可以使用切面环绕来实现一些跨越多个模块的通用逻辑。切面环绕可以在目标方法执行之前和之后执行一些自定义的业务逻辑,同时也可以修改目标方法的返回值或处理异常。 首先,我们需要创建一个切面类,通过使用Spring提供的注解来定义切面的具体逻辑。我们可以使用@Aspect注解将一个类标记为切面类,接着使用@Before、@After、@Around等注解来定义对应的切入点和通知类型。 在切面类中,我们需要定义一个环绕通知的方法,并在方法上使用@Around注解。在环绕通知方法中,我们可以通过ProceedingJoinPoint参数来获取目标方法的信息。可以利用这个参数,在目标方法执行之前编写一些逻辑,在目标方法执行之后编写一些逻辑。同时,我们还可以通过proceed方法调用目标方法,并修改返回值或处理异常。 当定义好切面类后,我们需要在应用的配置类中启用切面。可以使用@EnableAspectJAutoProxy注解来启用切面的自动代理功能。这样,Spring Boot会自动根据切面类的注解配置生成对应的代理类,并在目标方法执行的时候,触发切面的逻辑。 总结来说,Spring Boot切面环绕是一种通过使用切面类来定义环绕通知,实现一些跨越多个模块的通用逻辑的方式。通过切面环绕可以在目标方法执行之前和之后编写自定义的业务逻辑,同时还可以修改返回值或处理异常。 ### 回答3: Spring Boot是一个用于构建独立的、生产级的Spring应用程序的框架。切面Aspect)是Spring框架中的一个重要概念,用于对程序中的特定方法进行拦截、增强或修改等操作。 在Spring Boot中使用切面环绕的方式,可以实现对目标方法进行前置、后置、异常和最终通知的处理。首先,我们需要创建一个切面类,并使用@Aspect注解进行标记。在切面类中,我们可以定义切点(Pointcut)和通知(Advice)。 切点指定了在何处拦截方法,可以使用@Pointcut注解进行定义。通知是在方法执行前后或发生异常时执行的一段代码,可以使用@Before、@After、@AfterReturning和@AfterThrowing等注解进行标记。在通知中,我们可以获取方法的参数、返回值和异常等信息,并根据需要进行处理。 除了使用注解方式,我们还可以通过编程方式配置切面环绕。可以继承org.aspectj.lang.annotation.AspectJProxyFactory类,并在其中添切点和通知等配置。然后,通过该类的getProxy()方法获取代理对象,并使用代理对象调用目标方法。 在使用切面环绕时,我们可以通过在应用的配置文件中添@EnableAspectJAutoProxy注解,来启用Spring的AOP功能。此外,我们还可以使用@Order注解来确定切面的执行顺序,使用@Around注解来实现对目标方法的环绕处理。 总之,Spring Boot切面环绕是一种强大的功能,它可以对程序中的特定方法进行拦截和增强等操作。通过使用切面环绕,我们可以实现非侵入式的功能扩展,提高代码的复用性和可维护性,并实现更好的业务逻辑控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值