Spring IOC 源码学习 环境准备

Spring 的工具类

源码有很多工具类 没必要造轮子

PropertiesLoader

PropertiesLoaderUtils 是 Spring 提供的属性文件加载工具类,位于 org.springframework.core.io.support 包下,相比 JDK 原生的 Properties 类,它能更便捷地加载类路径、文件系统、Jar 包内的 .properties/.yml(需配合其他工具)配置文件,无需手动处理流关闭、路径拼接等问题

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import java.util.Properties;
 
public class PropertiesLoaderAdvanceDemo {
    public static void main(String[] args) {
        try {
            // 指定类路径下的配置文件(支持多层目录)
            ClassPathResource resource = new ClassPathResource("config/db.properties");
            Properties props = PropertiesLoaderUtils.loadProperties(resource);
            
            String dbUrl = props.getProperty("db.url");
            System.out.println("数据库地址:" + dbUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

StopWatch

StopWatch 是 Spring 提供的任务耗时统计工具类,位于 org.springframework.util 包下,它能更优雅地记录单个 / 多个任务的执行时间,支持分段计时、总耗时统计、耗时格式化输出,常用于性能调试。

import org.springframework.util.StopWatch;
 
public class StopWatchAdvanceDemo {
    public static void main(String[] args) throws InterruptedException {
        StopWatch stopWatch = new StopWatch("用户注册流程耗时");
        
        // 任务1:参数校验
        stopWatch.start("参数校验");
        Thread.sleep(50);
        stopWatch.stop();
        
        // 任务2:数据库插入
        stopWatch.start("数据库插入用户数据");
        Thread.sleep(150);
        stopWatch.stop();
        
        // 任务3:发送短信验证码
        stopWatch.start("发送短信验证码");
        Thread.sleep(300);
        stopWatch.stop();
        
        // 核心API使用
        System.out.println("总耗时(毫秒):" + stopWatch.getTotalTimeMillis()); // 总耗时
        System.out.println("任务总数:" + stopWatch.getTaskCount()); // 任务数
        System.out.println("第一个任务名称:" + stopWatch.getTaskInfo()[0].getTaskName()); // 任务详情
        System.out.println("第二个任务耗时:" + stopWatch.getTaskInfo()[1].getTimeMillis() + "ms");
        
        // 美观的格式化输出
        System.out.println("\n===== 耗时详情 =====");
        System.out.println(stopWatch.prettyPrint());
    }
}

Bean属性设置 BeanWrapper

BeanWrapper 提供分析和操作标准JavaBeans的操作: 获取和设置属性值 (单独或批量),获取属性描述以及查询属性的能力。

PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);  
initBeanWrapper(bw);
 

注解工具类 Annotation

AnnotationUtils

用于处理注解、处理元注解、桥接方法(编译器会为通用声明生成)以及超级方法(用于可选注解继承)的通用实用方法。

请注意,JDK 的内省工具本身并不提供该类的大部分功能。 对于运行时保留的应用程序注解(例如,用于事务控制、授权或服务暴露),一般应始终使用该类的查找方法(例如,findAnnotation(Method, Class) 或 getAnnotation(Method, Class)),而不是 JDK 中的普通注解查找方法。您仍然可以明确选择只在给定类级别上进行获取查找(getAnnotation(Method, Class)),还是在给定方法的整个继承层次中进行查找(findAnnotation(Method, Class))。

import org.springframework.core.annotation.AnnotationUtils;
 
// 测试类
@MyAnnotation(value = "用户服务", desc = "处理用户相关逻辑")
class UserService {
    @MyAnnotation(value = "查询用户", desc = "根据ID查询用户信息")
    public void queryUserById(Long id) {}
}
 
public class AnnotationUtilsBasicDemo {
    public static void main(String[] args) throws NoSuchMethodException {
        // 1. 获取类上的注解
        MyAnnotation classAnnotation = AnnotationUtils.findAnnotation(UserService.class, MyAnnotation.class);
        System.out.println("类注解value:" + classAnnotation.value()); // 输出:用户服务
        System.out.println("类注解desc:" + classAnnotation.desc()); // 输出:处理用户相关逻辑
        
        // 2. 获取方法上的注解
        var method = UserService.class.getMethod("queryUserById", Long.class);
        MyAnnotation methodAnnotation = AnnotationUtils.findAnnotation(method, MyAnnotation.class);
        System.out.println("方法注解value:" + methodAnnotation.value()); // 输出:查询用户
        
        // 3. 获取注解的指定属性(兼容别名)
        String desc = AnnotationUtils.getValue(methodAnnotation, "desc").toString();
        System.out.println("方法注解desc:" + desc); // 输出:根据ID查询用户信息
    }
}

AnnotatedElementUtils

用于在AnnotatedElements上查找注释、元注释和可重复注释的通用实用程序方法。

AnnotatedElementUtils为Spring的元注释编程模型定义了公共API,并支持注释属性重写。如果不需要对注释属性重写的支持,请考虑改用AnnotationUtils。