springboot 自定义切面类

 

首先讲AOP切面概念:

AOP(Aspect Oriented Programing):面向切面编程,将通用的逻辑从业务逻辑中分离出来。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离”。

       相关概念:

        连接点(Joinpoint): 表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点;在AOP中表示为“在哪里干”;

        切入点(Pointcut): 选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法;在AOP中表示为“在哪里干的集合”;

        通知(Advice): 在连接点上执行的行为,通知提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置通知(before advice)、后置通知(after advice)、环绕通知(around advice),在Spring中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入通知;在AOP中表示为“干什么”;

        切面(Aspect):横切关注点的模块化,比如日志组件。可以认为是通知、引入和切入点的组合;在Spring中可以使用Schema和@AspectJ方式进行组织实现;在AOP中表示为“在哪干和干什么集合”;
        引入(Introduction): 也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象);在AOP中表示为“干什么(引入什么)”;
        目标对象(Target Object):需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为“被通知对象”;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象;在AOP中表示为“对谁干”;
        AOP代理(AOP Proxy): AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。
        织入(Weaving): 织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期进行。组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。


/*
 * @description: 多语言切面
 */
@Aspect
@Component
// 切面启用条件:配置文件中language=true
@ConditionalOnProperty(prefix = "language",name = "enabled",havingValue = "true")
@Slf4j
public class LanguageAspect {

    @Autowired
    private CommonAPI commonAPI;

    @Autowired
    private ISysLanguageService sysLanguageService;
    @Autowired
    private SysLanguageMapper sysLanguageMapper;

    // 定义切点Pointcut
    @Pointcut("execution(public * com.modules..*.*Controller.*(..))")
    public void excudeService() {
    }

    //环绕通知:灵活自由的在目标方法中切入代码
    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long time1=System.currentTimeMillis();
        Object result  = this.parseLanguageFiled(pjp);
        long time2=System.currentTimeMillis();
        log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms");
        long start=System.currentTimeMillis();
        long end=System.currentTimeMillis();
        log.debug("解析注入JSON数据  耗时"+(end-start)+"ms");
        return result;
    }


    /**
     * 解析多语言字段
     * @param pjp
     * @return
     * @throws Throwable
     */
    private Object parseLanguageFiled(ProceedingJoinPoint pjp) throws Throwable {
        // 获取目标方法的名称
        // String methodName = pjp.getSignature().getName();
        // 获取方法传入参数
        // Object[] params = pjp.getArgs();
        // 反射获取目标类
        // Class<?> targetClass = pjp.getTarget().getClass();
        // 拿到方法对应的参数类型
        // Class<?>[] parameterTypes = ((MethodSignature)        pjp.getSignature()).getParameterTypes();
        // 根据类、方法、参数类型(重载)获取到方法的具体信息
        // Method objMethod = targetClass.getMethod(methodName, parameterTypes);
        // 拿到方法定义的注解信息 @Dict
        // Dict annotation = objMethod.getDeclaredAnnotation(Dict.class);
        // 执行切入点方法
        Object result = pjp.proceed();
        if (result instanceof Result) {
            // 列表页面展示
            if (((Result) result).getResult() instanceof IPage) {
                List<JSONObject> items = new ArrayList<>();
                //多语言  业务id
                List relBizIds = new ArrayList();
                for (Object record : ((IPage) ((Result) result).getResult()).getRecords()) {
                    ObjectMapper mapper = new ObjectMapper();
                    String json="{}";
                    try {
                        //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
                        json = mapper.writeValueAsString(record);
                    } catch (JsonProcessingException e) {
                        log.error("json解析失败"+e.getMessage(),e);
                    }
                    JSONObject item = JSONObject.parseObject(json);
                    //多语言  业务id
                    if(item.get("id") != null){
                        relBizIds.add(item.get("id"));
                    }
                    items.add(item);
                }
                List languageList = new ArrayList();
                if(null != relBizIds && relBizIds.size() > 0){
                    languageList = sysLanguageService.queryLanguageListForTable(relBizIds);
                }
                ((Result) result).setLanguageList(languageList);
            } else if (((Result) result).getResult() instanceof List){
                // 详情页,查看明细时
                for (Object record : (List)((Result) result).getResult()) {
                    ObjectMapper mapper = new ObjectMapper();
                    String json="{}";
                    try {
                        //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
                        json = mapper.writeValueAsString(record);
                    } catch (JsonProcessingException e) {
                        log.error("json解析失败"+e.getMessage(),e);
                    }
                    JSONObject item = JSONObject.parseObject(json);
                    //多语言  业务id
                    if(item.get("id") != null && item.containsKey("sysLanguageList")){
                        String bizId = (String)item.get("id");
                        log.info("多语言切面————获取业务明细id:"+bizId);
                        try{
                            Field field = record.getClass().getSuperclass().getDeclaredField("sysLanguageList");
                            if(null != field){
                                // 查询多语言配置
                                List dtlLanguageList = new ArrayList();
                                List relBizIds = new ArrayList();
                                relBizIds.add(bizId);
                                dtlLanguageList = sysLanguageService.queryLanguageListForTable(relBizIds);
                                // 返回多语言结果
                                field.setAccessible(true);
                                field.set(record, dtlLanguageList);
                                field.setAccessible(false);
                                log.info("多语言切面————业务明细多语言配置:"+dtlLanguageList.size()+"条");

                            }
                        }catch (Exception e){
                            log.error("切面查询多语言时,缺少多语言属性sysLanguageList。"+e.getMessage(),e);
                            continue;
                        }


                    }
                }

            }

            return result;
        }
        return result;
    }

}

参考链接:

https://blog.csdn.net/u012050154/article/details/77370297

https://www.cnblogs.com/lingyejun/p/9941350.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值