• Spring之美- IOC和AOP


    Spring IOC

    IoC(控制反转)是一种设计思想,将原本需要在程序中手动创建对象的控制权,交由Spring框架来管理。IoC容器是Spring用来实现IoC的载体,IoC容器实际上就是一个Map(Key,value),Map中存放的是各种对象。
    将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IoC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何创建的。
    Spring IoC初始化过程:
    在这里插入图片描述
    如何解决循环依赖
    使用三级缓存。
    第一级缓存singletonObjects里面放置的是实例化好的单例对象。
    第二级earlySingletonObjects里面存放的是提前曝光的单例对象(没有完全装配好)。
    第三级singletonFactories里面存放的是要被实例化的对象的对象工厂。

    Spring AOP

    AOP(面向切面编程)核心思想是将业务逻辑中与类不相关的通用功能切面式的提取分离出来,让多个类共享一个行为,一旦这个行为发生改变,不必修改类,而只需要修改这个行为即可。(例如事务处理、日志管理、权限控制)封装起来,减少系统的重复代码,降低代码之间的耦合度,并有利于未来的可扩展性和可维护性。

    五种环绕方式

    • 前置通知 (@Before)
    • 返回通知 (@AfterReturning)
    • 异常通知 (@AfterThrowing)
    • 后置通知 (@After)
    • 环绕通知 (@Around)

    OOP与AOP的区别

    OOP是面向对象编程,核心思想是将客观存在的不同事物抽象成相互独立的类,然后把与事物相关的属性和行为封装到类里,并通过继承和多态来定义类彼此间的关系,最后通过操作类的实例来完成实际业务逻辑的功能需求。
    OOP与AOP的区别:
    1、面向目标不同:简单来说OOP是面向名词领域,AOP面向动词领域。
    2、思想结构不同:OOP是纵向结构,AOP是横向结构。
    3、注重方面不同:OOP注重业务逻辑单元的划分,AOP偏重业务处理过程的某个步骤或阶段。

    配置AOP切面

    • @Aspect:标识切面
    • @Pointcut:设置切点,这里以自定义注解为切点,定义切点有很多其它种方式,自定义注解是比较常用的一种。
    • @Before:在切点之前织入,打印了一些入参信息
    • @Around:环绕切点,打印返回参数和接口执行时间
    package com.ym.blog.api.annotation;
    
    import java.lang.annotation.*;
    
    /**
     * 日志注解
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface LogAnnotation {
    
        String module() default "";
    
        String operation() default "";
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在需要使用切面的地方,注解即可。

    package com.ym.blog.api.aop;
    
    import com.alibaba.fastjson.JSON;
    import com.ym.blog.api.annotation.LogAnnotation;
    import com.ym.blog.api.utils.HttpContextUtil;
    import com.ym.blog.api.utils.IpUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    /**
     * @Author: Yangmiao
     * @Date: 2022/9/13 20:58
     * @Desc: 日志切面
     */
    @Aspect
    @Component
    @Slf4j
    public class LogAspect {
    
        @Pointcut("@annotation(com.ym.blog.api.annotation.LogAnnotation)")
        public void logPointCut(){
    
        }
    
        @Around("logPointCut()")
        public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
            long startTime = System.currentTimeMillis();
    
            Object proceed = proceedingJoinPoint.proceed();
    
            long time = System.currentTimeMillis()-startTime;
    
            recordLog(time,proceedingJoinPoint);
            return proceed;
        }
    
        private void recordLog(long time, ProceedingJoinPoint joinPoint) {
            MethodSignature signature = (MethodSignature)joinPoint.getSignature();
            Method method = signature.getMethod();
            LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
            log.info("=====================log start================================");
            log.info("module:{}",logAnnotation.module());
            log.info("operation:{}",logAnnotation.operation());
    
            // 请求的方法名
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = signature.getName();
            log.info("request method:{}",className + "." + methodName + "()");
    
            // 请求的参数
            Object[] args = joinPoint.getArgs();
            String params = JSON.toJSONString(args[0]);
            log.info("params: {}",params);
    
            // 请求的ip
            log.info("ip address: {}", IpUtils.getIpAddr(HttpContextUtil.getHttpServletRequest()));
    
            log.info("excute time : {} ms",time);
            log.info("=====================log end================================");
        }
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    欢迎大家关注个人微信公众号:一杯Java不加糖呢,不定期更新文章,谢谢🙏~
    在这里插入图片描述

  • 相关阅读:
    微服务系列二:微服务架构面临的挑战
    ANSYS Workbench18.0有限元仿真分析视频教程
    计算机毕业设计 基于SSM的民宿推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
    049:vue+openlayers鼠标pointermove显示城市名片(示例代码)
    (附源码)基于springboot的物流配货管理系统的设计与实现 毕业设计 250858
    基于高德地图实现Android定位功能实现(二)
    直播案例剖析:手机降频对直播声音体验的影响
    Python网络爬虫5-实战网页爬取
    DAC芯片AD5689控制代码SPI接口FPGA代码,视频
    Bootstrap中的栅格系统
  • 原文地址:https://blog.csdn.net/baidu_33256174/article/details/127600947