精华内容
下载资源
问答
  • 切面注解怎么实现
    2021-05-24 16:14:34

    目的:实现在任何想要切的地方添加一个注解就能实现面向切面编程

    编写一个自定义注解类:

    @Target({ElementType.PARAMETER, ElementType.METHOD})    
    @Retention(RetentionPolicy.RUNTIME)  
    public @interface LongOu {
        
    }
    

    @Target,@Retention都是java的元注解(总共有4个):
    @Target:设置注解的使用范围,这里设置可以用在参数上和方法上。
    @Retention:设置注解的生命周期,这里设置在运行时。
    切面类:

    @Aspect//声明这是一个切面
    @Component//把这个类交给spring管理
    public class LogOuAspect {
        // 把切面的连接点放在了我们的注解上
        @Pointcut("@annotation(com.example.demo.log.LongOu)")
        public void ouAspect() {
        }
        // 在这里定义前置切面
        @Before("ouAspect()")
        public void beforeMethod(JoinPoint joinPoint) {
            
            // 这里执行保存日志的动作
            System.out.println("方法前.......");
            //得到被切方法的参数
            System.out.println(joinPoint.getArgs()[0]);
        }
    }
    

    conctronller类:

    @RestController  //springboot注解,类下的所有方法返回的数据类型为jason
    public class AspectController {
        @RequestMapping("/getUser")
        @LongOu//这是我们自定义的注解,加上这个注解后就能够切到这个方法了。
        public User getUser(@PathVariable Integer id,HttpServletRequest request) {
            System.out.println("方法中。。。。。");
            User user=new User();
            user.setName("小明");
            user.setPassword("xxxx");
            return user;
        }
    }
    

    实体类:

    public class User {
        Integer id;
        String name;
        String password;
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }
    

    运行结果:
    方法前…
    方法中。。。。。

    本文转载于->https://www.cnblogs.com/tongkey/p/8371833.html

    更多相关内容
  • 主要介绍了Spring AOP面向切面编程实现原理方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Java Springboot切面+注解实现数据脱敏

    千次阅读 2021-08-16 22:19:20
    Java Springboot切面+注解实现数据脱敏1. 业务概述2. 设计编码2.1 脱敏类型枚举2.2 脱敏注解2.3 脱敏工具类2.4 统一拦截器2.5 统一结果集2.6 用户实体类2.7 用户控制类3. 实现验证 1. 业务概述 随着互联网发展日益...

    1. 业务概述

    随着互联网发展日益繁盛,数据安全也越来越受到人们重视,数据脱敏一方面为了数据安全,另一方面也是为了符合法务合规规范。
    本文主要实现特殊字段脱敏响应,通过切面+注解实现数据脱敏。
    通过切面获取指定脱敏类型,实现将数据统一脱敏返回。

    2. 设计编码

    2.1 脱敏类型枚举

    package com.example.category.desen;
    
    /**
     * 脱敏类型枚举
     *
     * @author zrj
     * @since 2021/8/16
     **/
    public enum SensitiveTypeEnum {
        /**
         * 中文名
         */
        CHINESE_NAME,
        /**
         * 身份证号
         */
        ID_CARD,
        /**
         * 座机号
         */
        FIXED_PHONE,
        /**
         * 手机号
         */
        MOBILE_PHONE,
        /**
         * 地址
         */
        ADDRESS,
        /**
         * 电子邮件
         */
        EMAIL,
        /**
         * 银行卡
         */
        BANK_CARD,
        /**
         * 公司开户银行联号
         */
        CNAPS_CODE;
    }
    
    

    2.2 脱敏注解

    package com.example.category.desen;
    
    import java.lang.annotation.*;
    
    /**
     * 脱敏注解
     *
     * @author zrj
     * @since 2021/8/16
     **/
    @Inherited
    @Documented
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Desensitized {
        /**
         * 脱敏类型(规则)
         */
        SensitiveTypeEnum type();
    }
    
    

    2.3 脱敏工具类

    package com.example.category.desen;
    
    import com.example.category.entity.Response;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang.ArrayUtils;
    import org.apache.commons.lang.StringUtils;
    
    import java.lang.reflect.Array;
    import java.lang.reflect.Field;
    import java.util.*;
    
    /**
     * 脱敏工具类
     *
     * @author zrj
     * @since 2021/8/16
     **/
    @Slf4j
    public class DesensitizedUtil {
    
        /**
         * 脱敏工具开关,0:关闭,1:开启
         */
        public static final String DESENT_STATUS = "1";
    
        /**
         * 脱敏数据
         *
         * @param obj
         * @return void
         */
        public static void desentData(Object obj) throws IllegalAccessException {
            if (null == obj) {
                return;
            }
    
            //如果是原始类型,则忽略处理
            if (obj.getClass().isPrimitive()) {
                return;
            }
            // 是否是接口
            if (obj.getClass().isInterface()) {
                return;
            }
    
            Object data = null;
            Class<?> clazz = null;
            //如果是通用的分页响应对象,则对该对象内部的List<T>进行脱敏
            if (obj.getClass().equals(Response.class)) {
                data = ((Response) obj).getData();//这里是自定义返回对象
                clazz = data.getClass();
                if (null == clazz) {
                    return;
                }
            }
    
            // 获取所有属性
            Field[] fields = clazz.getDeclaredFields();
            while (null != clazz.getSuperclass() && !Object.class.equals(clazz.getSuperclass())) {
                fields = (Field[]) ArrayUtils.addAll(fields, clazz.getSuperclass().getDeclaredFields());
                clazz = clazz.getSuperclass();
            }
    
            if (null == fields && fields.length == 0) {
                return;
            }
    
            for (Field field : fields) {
                field.setAccessible(true);
                if (null == field) {
                    return;
                }
                Object value = field.get(data);
                if (null != value) {
                    Class<?> type = value.getClass();
    
                    // 1.处理子属性,包括集合中的
                    if (type.isArray()) {
                        int len = Array.getLength(value);
                        for (int i = 0; i < len; i++) {
                            Object arrayObject = Array.get(value, i);
                            DesensitizedUtil.desentData(arrayObject);
                        }
                    } else if (value instanceof Collection<?>) {
                        Collection<?> c = (Collection<?>) value;
                        Iterator<?> it = c.iterator();
                        while (it.hasNext()) {
                            Object collectionObj = it.next();
                            DesensitizedUtil.desentData(collectionObj);
                        }
                    } else if (value instanceof Map<?, ?>) {
                        Map<?, ?> m = (Map<?, ?>) value;
                        Set<?> set = m.entrySet();
                        for (Object o : set) {
                            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
                            Object mapVal = entry.getValue();
                            DesensitizedUtil.desentData(mapVal);
                        }
                    } else if (!type.isPrimitive()
                            && !StringUtils.startsWith(type.getPackage().getName(), "javax.")
                            && !StringUtils.startsWith(type.getPackage().getName(), "java.")
                            && !StringUtils.startsWith(field.getType().getName(), "javax.")
                            && !StringUtils.startsWith(field.getName(), "java.")) {
                        DesensitizedUtil.desentData(type);
                    }
                }
    
                // 2. 处理自身的属性
                Desensitized annotation = field.getDeclaredAnnotation(Desensitized.class);
                if (field.getType().equals(String.class) && null != annotation) {
                    String valueStr = (String) field.get(data);
                    if (StringUtils.isNotBlank(valueStr)) {
                        switch (annotation.type()) {
                            case CHINESE_NAME: {
                                field.set(data, DesensitizedUtil.chineseName(valueStr));
                                break;
                            }
                            case ID_CARD: {
                                field.set(data, DesensitizedUtil.idCardNum(valueStr));
                                break;
                            }
                            case FIXED_PHONE: {
                                field.set(data, DesensitizedUtil.fixedPhone(valueStr));
                                break;
                            }
                            case MOBILE_PHONE: {
                                field.set(data, DesensitizedUtil.mobilePhone(valueStr));
                                break;
                            }
                            case ADDRESS: {
                                field.set(data, DesensitizedUtil.address(valueStr, 4));
                                break;
                            }
                            case EMAIL: {
                                field.set(data, DesensitizedUtil.email(valueStr));
                                break;
                            }
                            case BANK_CARD: {
                                field.set(data, DesensitizedUtil.bankCard(valueStr));
                                break;
                            }
                            case CNAPS_CODE: {
                                field.set(data, DesensitizedUtil.cnapsCode(valueStr));
                                break;
                            }
                            default: {
                                break;
                            }
                        }
                    }
                }
            }
    
        }
    
    
        /**
         * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**>
         *
         * @param fullName 中文姓名
         * @return 中文姓名
         */
        private static String chineseName(String fullName) {
            if (StringUtils.isBlank(fullName)) {
                return "";
            }
            String name = StringUtils.left(fullName, 1);
            return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
        }
    
        /**
         * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**>
         *
         * @param familyName 中文姓名
         * @param givenName  中文姓名
         * @return
         */
        private static String chineseName(String familyName, String givenName) {
            if (StringUtils.isBlank(familyName) || StringUtils.isBlank(givenName)) {
                return "";
            }
            return chineseName(familyName + givenName);
        }
    
        /**
         * [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。<例子:*************5762>
         *
         * @param id 身份证号
         * @return 身份证号
         */
        private static String idCardNum(String id) {
            if (StringUtils.isBlank(id)) {
                return "";
            }
            String num = StringUtils.right(id, 4);
            return StringUtils.leftPad(num, StringUtils.length(id), "*");
        }
    
        /**
         * [固定电话] 后四位,其他隐藏<例子:****1234>
         *
         * @param num 固定电话
         * @return 固定电话
         */
        private static String fixedPhone(String num) {
            if (StringUtils.isBlank(num)) {
                return "";
            }
            return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");
        }
    
        /**
         * [手机号码] 前三位,后四位,其他隐藏<例子:138******1234>
         *
         * @param num 手机号码
         * @return String
         */
        private static String mobilePhone(String num) {
            if (StringUtils.isBlank(num)) {
                return "";
            }
            return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*"), "***"));
        }
    
        /**
         * [地址] 只显示到地区,不显示详细地址;我们要对个人信息增强保护<例子:北京市海淀区****>
         *
         * @param address       地址
         * @param sensitiveSize 敏感信息长度
         * @return String
         */
        private static String address(String address, int sensitiveSize) {
            if (StringUtils.isBlank(address)) {
                return "";
            }
            int length = StringUtils.length(address);
            return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");
        }
    
        /**
         * [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示<例子:g**@163.com>
         *
         * @param email 电子邮箱
         * @return String
         */
        private static String email(String email) {
            if (StringUtils.isBlank(email)) {
                return "";
            }
            int index = StringUtils.indexOf(email, "@");
            if (index <= 1) {
                return email;
            } else {
                return StringUtils.rightPad(StringUtils.left(email, 1), index, "*").concat(StringUtils.mid(email, index, StringUtils.length(email)));
            }
        }
    
        /**
         * [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:6222600**********1234>
         *
         * @param cardNum 银行卡号
         * @return String
         */
        private static String bankCard(String cardNum) {
            if (StringUtils.isBlank(cardNum)) {
                return "";
            }
            return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
        }
    
        /**
         * [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号<例子:12********>
         *
         * @param code 卡号
         * @return java.lang.String
         */
        private static String cnapsCode(String code) {
            if (StringUtils.isBlank(code)) {
                return "";
            }
            return StringUtils.rightPad(StringUtils.left(code, 2), StringUtils.length(code), "*");
        }
    }
    
    

    2.4 统一拦截器

    package com.example.category.desen;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * 统一拦截器
     *
     * @author zrj
     * @since 2021/8/16
     **/
    @Aspect
    @Configuration
    public class SensitiveAspect {
        public static final String ACCESS_EXECUTION = "execution(* com.example.category.controller..*.*(..))";
    
        /**
         * 注解脱敏处理
         */
        @Around(ACCESS_EXECUTION)
        public Object sensitiveClass(ProceedingJoinPoint joinPoint) throws Throwable {
            return sensitiveFormat(joinPoint);
        }
    
        /**
         * 注解统一拦截器
         */
        public Object sensitiveFormat(ProceedingJoinPoint joinPoint) throws Throwable {
            Object obj = joinPoint.proceed();
            if (obj == null || isPrimitive(obj.getClass())) {
                return obj;
            }
    
            if (DesensitizedUtil.DESENT_STATUS.equals("1")) {
                DesensitizedUtil.desentData(obj);
            }
            return obj;
        }
    
        /**
         * 基本数据类型和String类型判断
         */
        public static boolean isPrimitive(Class<?> clz) {
            try {
                if (String.class.isAssignableFrom(clz) || clz.isPrimitive()) {
                    return true;
                } else {
                    return ((Class) clz.getField("TYPE").get(null)).isPrimitive();
                }
            } catch (Exception e) {
                return false;
            }
        }
    }
    
    

    2.5 统一结果集

    package com.example.category.entity;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    /**
     * 统一结果集
     *
     * @author zrj
     * @date 2021/6/2
     * @since V1.0
     **/
    @Data
    @Component
    public class Response<T> {
        public static ResponseCode responseCode;
        /**
         * 提示消息
         */
        public String message;
    
        /**
         * 具体返回的数据
         */
        public T data;
    
        /**
         * 状态码
         */
        public String code;
    
        public Response(String code, String message, T data) {
            this.message = message;
            this.code = code;
            this.data = data;
        }
    
        public Response(String code, String msg) {
            this.message = msg;
            this.code = code;
        }
    
        @Autowired
        public Response(ResponseCode responseCode) {
            Response.responseCode = responseCode;
        }
    
        /**
         * 返回成功Response对象
         */
        public static <T> Response<T> success(String successMessage, T data) {
            return new Response<>(responseCode.getSuccessCode(), successMessage, data);
        }
    
        /**
         * 返回错误Response对象
         */
        public static <T> Response<T> fail(String errorMessage) {
            return new Response<>(responseCode.getErrorCode(), errorMessage);
        }
    }
    
    
    package com.example.category.entity;
    
    import lombok.Data;
    import org.springframework.stereotype.Component;
    
    /**
     * 响应码
     *
     * @author zrj
     * @date 2021/6/2
     * @since V1.0
     **/
    @Data
    @Component
    public class ResponseCode {
        public String successCode = "200";
    
        public String errorCode = "500";
    
        public String authErrorCode = "300";
    }
    
    

    2.6 用户实体类

    package com.example.category.entity;
    
    import com.example.category.desen.Desensitized;
    import com.example.category.desen.SensitiveTypeEnum;
    import lombok.Data;
    
    import java.io.Serializable;
    
    /**
     * 用户实体类
     *
     * @author zrj
     * @since 2021-06-21
     */
    @Data
    public class User implements Serializable {
        private static final long serialVersionUID = -37201319317456395L;
        /**
         * id
         */
        private Integer id;
    
        /**
         * 姓名
         */
        @Desensitized(type = SensitiveTypeEnum.CHINESE_NAME)
        private String name;
    
        /**
         * 手机号
         */
        @Desensitized(type = SensitiveTypeEnum.MOBILE_PHONE)
        private String mobilePhone;
    
        /**
         * 身份证号码
         */
        @Desensitized(type = SensitiveTypeEnum.ID_CARD)
        private String idCard;
    
        /**
         * 地址
         */
        @Desensitized(type = SensitiveTypeEnum.ADDRESS)
        private String address;
    
        /**
         * 邮箱
         */
        @Desensitized(type = SensitiveTypeEnum.EMAIL)
        private String email;
    }
    

    2.7 用户控制类

    package com.example.category.controller;
    
    import com.example.category.entity.User;
    import com.example.category.service.UserService;
    import io.swagger.annotations.Api;
    import org.springframework.web.bind.annotation.*;
    import com.example.category.entity.Response;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    
    /**
     * 用户控制类
     *
     * @author makejava
     * @since 2021-06-21 16:44:24
     */
    @RestController
    @RequestMapping("/user")
    @Api(tags = "用户管理", description = "用户管理")
    public class UserController {
        /**
         * 脱敏测试
         */
        @RequestMapping(value = "test", method = RequestMethod.GET)
        public Response<User> test() {
            User result = new User();
            result.setId(1);
            result.setName("王小二");
            result.setMobilePhone("13057631239");
            result.setIdCard("320102199303073260");
            result.setAddress("中国上海市张江高新区256号");
            result.setEmail("hello@163.com");
    
            if (result != null) {
                return Response.success("查询成功", result);
            }
            return Response.fail("查询失败");
        }
    }
    

    3. 实现验证

    在这里插入图片描述

    展开全文
  • } } 编写切入类: //将该类交给spring来管理 @Component //表明当前类是一个切面类 @Aspect //使用该注解可以开启注解AOP的支持,不必在spring核心配置文件beans.xml配置 //@EnableAspectJAutoProxy public class ...

    准备工作

    1. maven添加依赖AOP切入点表达式
    <!--        用于解析AOP切入点表达式-->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.6</version>
            </dependency>
    

    使用注解配置实现AOP

    1. 编写业务类
    //将该类交给spring来管理
    @Service
    public class AccountServiceImpl implements AccountService {
        public void saveAccount() {
            System.out.println("保存了数据");
           // int i=1/0;
        }
    
        public void updateAccount(String i) {
            System.out.println("更新了数据"+i);
        }
    
        public int deleteAccount() {
            System.out.println("删除了数据");
            return 0;
        }
    
    }
    
    1. 编写切入类:
    //将该类交给spring来管理
    @Component
    //表明当前类是一个切面类
    @Aspect
    //使用该注解可以开启注解AOP的支持,不必在spring核心配置文件beans.xml配置<aop:aspectj-autoproxy/>
    //@EnableAspectJAutoProxy
    public class Logger {
    
        @Pointcut("execution(* com.chenhui.service.AccountServiceImpl.*(..))")
        private void pc(){}
    
    
        //用于打印日志,计划让其在切入点方法执行之前执行(前置通知)
        @Before("pc()")
        public void beforePrintLog(){
            System.out.println("Logger类中的beforePrintLog()方法开始记录日志了");
        }
        //(后置通知)
        @AfterReturning("pc()")
        public void afterReturningPrintLog(){
            System.out.println("Logger类中的afterReturningPrintLog()方法开始记录日志了");
        }
        //异常通知
        @AfterThrowing("pc()")
        public void afterThrowingPrintLog(){
            System.out.println("Logger类中的afterThrowingPrintLog()方法开始记录日志了");
        }
        //最终通知
        @After("pc()")
        public void afterPrintLog(){
            System.out.println("Logger类中的afterPrintLog()方法开始记录日志了");
        }
    }    
    
    
    1. 在spring核心配置文件配置
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!--    配置spring容器创建时需要扫描的包-->
            <context:component-scan base-package="com.chenhui"></context:component-scan>
    
    <!--配置Spring开启注解AOP的支持-->
            <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>
    

    测试类:

    public class TestMain {
        public static void main(String[] args) {
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans.xml");
            //注意:此时获取出的bean对象是一个proxy类型的类,它是AccountService的一个实现类,也是代理类,
            //此时不能传入AccountServiceImpl.class,因为他们是同级,不能转化,只能通过接口转化,他们都是实现了AccountService接口
            AccountService accountService = applicationContext.getBean("accountServiceImpl", AccountService.class);
            //执行方法
            accountService.saveAccount();
    
        }
    }
    

    结果:
    在这里插入图片描述

    注意:

    通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring 在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了
    <aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class=“true”/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。

    展开全文
  • SpringBoot项目 Spring AOP切面注解实现

    千次阅读 2019-03-30 01:58:46
    //切面拦截器,拦截订单接口请求中是否能查询到token(类似SpringAOP) @Pointcut("execution(public * com.imooc.controller.Seller*.*(..))" + "&& !execution(public * ...

    这个类对控制层controller中的一些订单请求进行了拦截,并判断这些请求中Cookie中是否查到token(微信用户id) 

    import com.imooc.constant.CookieConstant;
    import com.imooc.constant.RedisConstant;
    import com.imooc.exception.SellerAuthorizeException;
    import com.imooc.utils.CookieUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * Created by 廖师兄
     * 2017-07-30 17:31
     */
    
    @Aspect //声明表示这是一个切面类
    @Component
    @Slf4j
    public class SellerAuthorizeAspect {
    
        @Autowired
        private StringRedisTemplate redisTemplate;
    
        //切面拦截器,拦截订单接口请求中是否能查询到token(类似SpringAOP)
        @Pointcut("execution(public * com.imooc.controller.Seller*.*(..))" +
        "&& !execution(public * com.imooc.controller.SellerUserController.*(..))") //切入点
        public void verify() {}
    
        @Before("verify()")  //在请求之前
        public void doVerify() {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            //查询cookie
            Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN);
            if (cookie == null) {
                log.warn("【登录校验】Cookie中查不到token");
                throw new SellerAuthorizeException();
            }
    
            //去redis里查询
            String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue()));
            if (StringUtils.isEmpty(tokenValue)) {
                log.warn("【登录校验】Redis中查不到token");
                throw new SellerAuthorizeException();
            }
        }
    }

    三、注解

    2 注解说明

    2.1 @Aspect

    作用是把当前类标识为一个切面供容器读取

    2.2 @Before
    标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有

    2.3 @AfterReturning

    后置增强,相当于AfterReturningAdvice,方法正常退出时执行

    2.4 @AfterThrowing

    异常抛出增强,相当于ThrowsAdvice

    2.5 @After

    final增强,不管是抛出异常或者正常退出都会执行

    2.6 @Around

    环绕增强,相当于MethodInterceptor

    2.7 @DeclareParents

    引介增强,相当于IntroductionInterceptor

    3 execution切点函数

     

    execution函数用于匹配方法执行的连接点,语法为:

    execution(方法修饰符(可选)  返回类型  方法名  参数  异常模式(可选)) 

     

    参数部分允许使用通配符:

    *  匹配任意字符,但只能匹配一个元素

    .. 匹配任意字符,可以匹配任意多个元素,表示类时,必须和*联合使用

    +  必须跟在类名后面,如Horseman+,表示类本身和继承或扩展指定类的所有类

     

    示例中的* chop(..)解读为:

    方法修饰符  无

    返回类型      *匹配任意数量字符,表示返回类型不限

    方法名          chop表示匹配名称为chop的方法

    参数               (..)表示匹配任意数量和类型的输入参数

    异常模式       不限

     

    更多示例:

    void chop(String,int)

    匹配目标类任意修饰符方法、返回void、方法名chop、带有一个String和一个int型参数的方法

    public void chop(*)

    匹配目标类public修饰、返回void、方法名chop、带有一个任意类型参数的方法

    public String *o*(..)

     匹配目标类public修饰、返回String类型、方法名中带有一个o字符、带有任意数量任意类型参数的方法

    public void *o*(String,..)

     匹配目标类public修饰、返回void、方法名中带有一个o字符、带有任意数量任意类型参数,但第一个参数必须有且为String型的方法

    也可以指定类:

    public void examples.chap03.Horseman.*(..)

    匹配Horseman的public修饰、返回void、不限方法名、带有任意数量任意类型参数的方法

    public void examples.chap03.*man.*(..)

    匹配以man结尾的类中public修饰、返回void、不限方法名、带有任意数量任意类型参数的方法

    指定包:

    public void examples.chap03.*.chop(..)

    匹配examples.chap03包下所有类中public修饰、返回void、方法名chop、带有任意数量任意类型参数的方法

    public void examples..*.chop(..)

    匹配examples.包下和所有子包中的类中public修饰、返回void、方法名chop、带有任意数量任意类型参数的方法
    可以用这些表达式替换StorageAdvisor中的代码并观察效果

    4 更多切点函数

    除了execution(),Spring中还支持其他多个函数,这里列出名称和简单介绍,以方便根据需要进行更详细的查询

    4.1 @annotation()

    表示标注了指定注解的目标类方法

    例如 @annotation(org.springframework.transaction.annotation.Transactional) 表示标注了@Transactional的方法

    4.2 args()

    通过目标类方法的参数类型指定切点

    例如 args(String) 表示有且仅有一个String型参数的方法

    4.3 @args()

    通过目标类参数的对象类型是否标注了指定注解指定切点

    如 @args(org.springframework.stereotype.Service) 表示有且仅有一个标注了@Service的类参数的方法

    4.4 within()

    通过类名指定切点

    如 with(examples.chap03.Horseman) 表示Horseman的所有方法

    4.5 target()

    通过类名指定,同时包含所有子类

    如 target(examples.chap03.Horseman)  且Elephantman extends Horseman,则两个类的所有方法都匹配

    4.6 @within()

    匹配标注了指定注解的类及其所有子类

    如 @within(org.springframework.stereotype.Service) 给Horseman加上@Service标注,则Horseman和Elephantman 的所有方法都匹配

    4.7 @target()

    所有标注了指定注解的类

    如 @target(org.springframework.stereotype.Service) 表示所有标注了@Service的类的所有方法

    4.8 this()

    大部分时候和target()相同,区别是this是在运行时生成代理类后,才判断代理类与指定的对象类型是否匹配

    5 逻辑运算符

    表达式可由多个切点函数通过逻辑运算组成

    5.1 &&

    与操作,求交集,也可以写成and

    例如 execution(* chop(..)) && target(Horseman)  表示Horseman及其子类的chop方法

    5.2 ||

    或操作,求并集,也可以写成or

    例如 execution(* chop(..)) || args(String)  表示名称为chop的方法或者有一个String型参数的方法

    5.3 !

    非操作,求反集,也可以写成not

    例如 execution(* chop(..)) and !args(String)  表示名称为chop的方法但是不能是只有一个String型参数的方法

    展开全文
  • 注解实现类 : InterfaceLogAspect : import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.fintell.dp3.api.async.AsyncTask; import lombok.extern.slf4j.Slf4j; @Aspect @...
  • spring中aop的注解实现方式简单实例  上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢。前面已经讲过aop的简单...在切面类(为切点服务的类)前用@Aspect注释修饰,声明为一个切面类。 ...
  • 快速使用注解方式实现aop切面编程

    千次阅读 2022-02-25 14:39:38
    // 是否需要打印日志 } // 切面 @Aspect @Configuration public class AopLogs { @Pointcut("@annotation(com.wsgw.htjc.frontend.utils.AnnoAopLogs)") // 设定切点 public void pointCut(){} // 环绕通知 @Around...
  • 1、自定义注解 /** * 自定义操作日志注解 * @author arli */ //METHOD是可注解在方法级别上 @Target(ElementType.METHOD) //注解在哪个阶段执行,会被编译... // 用户的操作详情(接口实现的操作) String opera
  • 使用注解 实现 切面编程 1.定义注解 @Target({ElementType.METHOD}) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface MsgSecCheck { String value(); int idx() default 0; } 2.定义切面...
  • Spring切面实现自定义注解

    千次阅读 2019-06-06 11:23:16
    1.首先写出一个自定义注解。 package com.salong.aspect.test; import java.lang.annotation.*; @Target(ElementType.METHOD) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface Login { ...
  • 1、相关依赖包org.springframework.bootspring-boot-starter-aoporg.aspectjaspectjrt1.8.62、定义切面类package com.bz.aspect;import com.bz.service.SysLogOperationService;import org.aspectj.lang....
  • 这是配套代码,如果看描述看不懂可以直接下载代码,惊醒研究,如有什么不合适的地方或者说修改的地方,可以提醒我,我到时候回一一修正以及完善
  • 今天主要说说如何通过自定义注解的方式,在 Spring Boot 中来实现 AOP 切面统一打印出入参日志。小伙伴们可以收藏一波。 废话不多说,进入正题 ! 目录 一、先看看切面日志输出效果 二、添加 AOP Maven
  • 十、使用注解定义切面

    千次阅读 2021-03-09 06:57:51
    一、本课目标掌握使用注解实现AOP的方法二、使用注解定义切面2.1简介AspectJ面向切面的框架,它扩展了Java语言,定义了AOP语法,能够在编译期提供代码的织入。@AspectJAspectJ5新增的功能,使用JDK5.0注解技术和正规...
  • 注解实现切面案例 菜鸟记录一下学习过程。 (1)首先定义一个注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String getValues() default "test ...
  • 更多python、PHP、JAVA教程请到友情连接: 菜鸟教程https://www.piaodoo.com 茂名一技http://www.enechn.comppt制作教程步骤 http://www.tpyjn.cn 兴化论坛...对注解实现切面案例: (1)定义一个注解 @Target(Ele
  • 何为AOP,AOP的注解详解,AOP的使用详例,以上内容尽在本文
  • 首先定义注解类 import java.lang.annotation.*; /** * @description: 保存或者修改字典权限判断注解 * @fileName: CommDictValidateAspect.java * @author: Sure * @createAt: 2021/12/13/013 16:14 * @updateBy: ...
  • JAVA实现简单的切面注解

    万次阅读 2019-08-22 00:31:07
    背景 今天在分析同事遇到一个springboot的注解和方法锁一起用而导致的问题(@...本文介绍java中其中一种(InvocationHandler)利用动态代理的方式实现的代理的方法,从而类似的机制我们推测出spring的切面...
  • * 切面获取的值就是cat.name的值,这里必须以root.开头,表示获取入参的属性值。 * */ @AnnotationDemo(channel="#root.name") public String methoDemo(Cat cat) { // todo 业务代码 }
  • 1.只需要在controller层增加自定义@RequestLog注解就可以实现了。 @RequestLog功能参数如下: 功能一:是否记录请求参数 功能二:是否记录请求日志 功能三:是否记录返回值 功能四:是否以debug形式记录 功能五:日志类型 ...
  • 通常我们有这种需求,某一个字段是由前台维护的:...在数据返回前通过切面把被注解的字段替换成该值的含义。 这里使用性别字段,键值关系为: M - 男 W - 女 新建注解 新建一个注解用于标识字段需要被切面处理 @Target(E
  • 面向切面的底层实现是什么?小编在这里举个例子吧 小编首先给出Spring全家桶,方便大家下载使用—->Spring全家桶 1.自定义代理对象代理类以及实现类 1.1 定义接口(ArithmeticCacluetator) public interface ...
  • 什么是基于注解切面实现 我们使用切面来非侵入式操作程序方法,常用的场景如日志记录、权限判断等。  下面我实现权限判断的切面。 分析:  要实现基于注解切面,我们要定义“注解”,定义切面,...
  • 自定义注解实现AOPAOP简要概述自定义注解annotation配置AOP切面使用 AOP简要概述 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。...
  • @Aspect // 标注这是一个切面 public class MyCutLog { @Before("execution(* com.weizu.service.impl.UserServiceImpl.*(..))") public void beforeMethod(){ System.out.println("不使用aop提供的API接口的前置")...
  • 自定义AOP处理业务实现日志记录

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 82,807
精华内容 33,122
关键字:

切面注解怎么实现