其实就是对以前文章的一个总结,单独再写一篇文章的原因是,自己对某些知识点有了一些理解,但最重要的一点是AI总结的比自己整理的简直是好太多了。

IOC

IoC(控制反转) 是一种设计思想:将对象的创建、组装和依赖关系的管理权,从代码中反转给Spring容器。你的代码不再主动 new 对象,而是由容器来创建并注入。

在这里插入图片描述

IoC容器主要管理什么(面试常问)

  1. Bean的实例化:容器负责创建对象(默认是单例)。

  2. Bean的依赖装配:容器负责将Bean所依赖的其他Bean注入进去(通过构造器、Setter或字段)。

  3. Bean的生命周期管理:容器负责管理Bean的初始化、销毁等生命周期回调。

依赖注入的三种方式

在这里插入图片描述

@Resource和@Autowired的区别

都是用来自动装配的,都可以放在属性字段上
@Autowired是spring声明的,@Resource是jdk声明的
@Autowired默认按照类型注入,如果类型有多个,则按照名称注入
@Resource默认按照名称注入,如果没有该名称的对象,则按照类型注入,如果两个都找不到就报错
(这里的名称和类型实际上就是指该类的对象的名称和该类)

Spring如何实现IoC(底层原理)

  1. 配置阶段:通过 XML、注解或Java配置类,定义Bean及其依赖关系。

  2. 解析与注册:Spring容器启动时,读取配置,解析为 BeanDefinition 对象,并注册到容器中。

  3. 实例化与装配:根据BeanDefinition,通过反射创建Bean实例,并按照配置进行依赖注入(构造器注入、Setter注入等)。

  4. 生命周期回调:Bean创建完成后,执行初始化方法(如 @PostConstruct),容器关闭时执行销毁方法。

Bean的作用域(常用两个)

在这里插入图片描述

AOP

AOP(面向切面编程) 是一种编程范式,它允许你将那些横切关注点(如日志、事务、权限校验)从业务逻辑中抽离出来,形成独立的模块(称为切面),在运行时通过动态代理机制织入到目标方法中。

在这里插入图片描述

在这里插入图片描述

“AOP的核心思想是将横切关注点从业务代码中分离,通过动态代理在运行时织入。在Spring中,我主要用到 @Aspect 定义切面,用 @Pointcut 定义切入点表达式,用5种通知(@Before、@After、@Around等)在目标方法的不同时机执行横切逻辑。底层实现是JDK动态代理或CGLIB代理,由Spring容器在Bean初始化时自动生成代理对象。我们项目里主要用于统一日志记录、接口耗时监控和权限校验,减少重复代码,提升维护性。”

package com.example.springbootstudy.aop;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * 使用AOP切Controller打印日志
 *
 * @author 阿无
 * @version 1.0.0
 * @since 2024/8/19 - 10:57
 */
@Aspect
@Component
public class LogAspect {

    private static Log logger = LogFactory.getLog(LogAspect.class);

    // 记录保存所有controller层的日志
    @Pointcut("execution(public * com.example.springbootstudy.controller..*.*(..))")
    public void pointCutControllerLog(){
    }


    @Around("pointCutControllerLog()")
    public Object controllerLog(ProceedingJoinPoint point) throws Throwable{
        return logCommon(point,null);
    }


    // 如果非Controller层也需要保存日志,则可以使用注解的形式

    // 另一种写法是
//    @Around("@annotation(com.example.springbootstudy.aop.SysLogAnno)")
    @Around("@annotation(sysLogAnno)")
    public Object sysLog(ProceedingJoinPoint point,SysLogAnno sysLogAnno) throws Throwable{
        return logCommon(point,sysLogAnno);
    }



    public Object logCommon(ProceedingJoinPoint point,SysLogAnno sysLogAnno) throws Throwable{


        Long startTime = System.currentTimeMillis();
        LocalDateTime localDateTimeStart = LocalDateTime.now();

        String className = point.getTarget().getClass().getName();
        String message = sysLogAnno!=null ? sysLogAnno.value():null;
        String methodName = point.getSignature().getName();
        Object[] args = point.getArgs();
        // 参数全部转换为字符串并以,分割  否则就是一个空字符串
        String argsString = args!=null ? Arrays.stream(args).map(Object::toString)
                .collect(Collectors.joining(",")) : "";

        // 1. 获取request对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        // 1.1 请求方式
        String requestMethod = request.getMethod();
        // 1.2 请求地址/路径
        String requestURI = request.getRequestURI();
        // 1.3 访问来源ip
        String remoteAddr = request.getRemoteAddr();
        // 1.4 还可以获取用户登录的信息 我们在这儿暂时不需要
        //  可以把Object强转成User类
        // Object user_var = request.getSession().getAttribute("user_var");

        SysLog sysLog = new SysLog(className,methodName, message, argsString, null,
                null, localDateTimeStart,null,null,requestMethod,requestURI,remoteAddr);


        Object result = point.proceed();
        Long endTime = System.currentTimeMillis();
        LocalDateTime localDateTimeEnd = LocalDateTime.now();

        // 但凡执行到这儿的就是成功的,异常往上抛就行,交给全局异常处理器
        sysLog.setStatus("success");
        sysLog.setResult(result!=null ? result.toString():null);
        sysLog.setLocalDateTimeEnd(localDateTimeEnd);
        sysLog.setTotalTime(endTime - startTime);


        // 理论上这个日志应该是保存在es中的应该
        logger.info("日志记录正常");
        logger.info(sysLog);

//        2024-08-19 19:57:03.555  INFO 19756 --- [nio-8080-exec-1] c.example.springbootstudy.aop.LogAspect  :
//              SysLog(className=com.example.springbootstudy.service.LogTestService, methodName=testLog, message=LogTestService,
//              args=1,jay, result=1 jay, status=success, localDateTimeStart=2024-08-19T19:57:03.552, localDateTimeEnd=2024-08-19T19:57:03.555,
//              totalTime=3, requestMethod=GET, requestURI=/testAnnoLog/1, remoteAddr=127.0.0.1)
//        2024-08-19 19:57:03.555  INFO 19756 --- [nio-8080-exec-1] c.example.springbootstudy.aop.LogAspect  : 日志记录正常
//        2024-08-19 19:57:03.555  INFO 19756 --- [nio-8080-exec-1] c.example.springbootstudy.aop.LogAspect  :
//              SysLog(className=com.example.springbootstudy.controller.LogTestController, methodName=testAnnoLog, message=null,
//              args=1,jay, result=1 jay, status=success, localDateTimeStart=2024-08-19T19:57:03.502, localDateTimeEnd=2024-08-19T19:57:03.555,
//              totalTime=56, requestMethod=GET, requestURI=/testAnnoLog/1, remoteAddr=127.0.0.1)


        // 这里的结果就是拦截的方法的结果
        return result;
    }

}


配置文件的优先级

优先级结论:bootstrap.yml / bootstrap.properties > application.yml ≈ application.properties(两者同级,避免混用)。

实际项目建议:

使用 bootstrap.yml:仅在需要接入Spring Cloud Config或配置中心时使用,且只放引导配置。

使用 application.yml:作为日常开发的主要配置文件,因为它结构清晰,支持层级关系。

避免使用 application.properties:除非是遗留项目,否则优先选择application.yml,保持配置方式统一。

一句话总结
bootstrap.yml 先加载,用于引导系统;application.yml 后加载,用于定义业务。同名的 application.properties 与 application.yml 不建议同时使用。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐