一、Spring容器基础架构
/**
* Zhouyu-Spring核心容器类
* 职责:加载配置、管理Bean定义、创建和管理Bean实例
*/
public class ZhouyuApplicationContext {
// 存储配置类的Class对象,用于获取扫描路径等配置信息
private Class configClass;
// Bean定义映射表:key=Bean名称, value=Bean元数据(类型、作用域等)
private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
// 单例对象池:缓存单例Bean实例(key=Bean名称)
private ConcurrentHashMap<String, Object> singletonObject = new ConcurrentHashMap<>();
/**
* 容器构造器
* @param configClass Spring配置类的Class对象
*/
public ZhouyuApplicationContext(Class configClass) {
this.configClass = configClass;
// 初始化容器:扫描包路径、注册Bean定义、初始化单例Bean
initialize();
}
/**
* 核心方法:根据Bean名称获取Bean实例
* @param beanName 要获取的Bean名称
* @return Bean实例对象
*/
public Object getBean(String beanName) {
// 具体实现将在第五部分完成
return null;
}
}
创建容器时传入配置类
public class Test {
public static void main(String[] args) {
// 创建Spring容器实例,传入配置类
ZhouyuApplicationContext context = new ZhouyuApplicationContext(AppConfig.class);
// 从容器中获取名为"userService"的Bean实例
UserService userService = (UserService) context.getBean("userService");
}
}
二、核心注解实现
1. 组件扫描注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 组件扫描注解:标识要扫描的包路径
* 只能标注在类上,运行时保留
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
/**
* 指定要扫描的包路径
* @return 包路径字符串(如"com.zhouyu.service")
*/
String value() default "";
}
2. 组件标识注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 组件标识注解:标记需要被容器管理的类
* 只能标注在类上,运行时保留
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
/**
* 指定Bean在容器中的名称
* @return Bean名称(如"userService")
*/
String value() default "";
}
3. 单例多利注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
/**
* 指定Bean是单例还是多礼
* @return (如"singleton"或"prototype")
*/
String value() default "";
}
三、配置类与Bean定义
配置类示例
/**
* Spring配置类示例
* 使用@ComponentScan指定扫描包路径
*/
@ComponentScan("com.zhouyu.service") // 扫描com.zhouyu.service包及其子包
public class AppConfig {
// 配置类可以包含其他配置信息
}
Bean定义类
/**
* Bean定义类:封装Bean的元数据信息
*/
public class BeanDefinition {
// Bean的Class类型(如UserService.class)
private Class type;
// Bean的作用域(singleton/prototype)
private String scope;
// Setter和Getter方法
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}
四、容器初始化流程
1. 扫描路径处理
/**
* 容器初始化方法
* 1. 解析配置类的@ComponentScan注解
* 2. 扫描指定包路径下的所有类文件
* 3. 创建所有单例Bean
*/
private void initialize() {
// 检查配置类是否有ComponentScan注解
if (configClass.isAnnotationPresent(ComponentScan.class)) {
// 获取注解实例
ComponentScan scan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
// 将包路径转换为文件系统路径(com.zhouyu.service -> com/zhouyu/service)
String path = scan.value().replace(".", "/");
// 获取类加载器
ClassLoader classLoader = getClass().getClassLoader();
// 获取资源在类路径中的位置
URL resource = classLoader.getResource(path);
// 将URL转为文件对象
File dir = new File(resource.getFile());
// 确保是目录
if (dir.isDirectory()) {
// 遍历目录下所有文件
for (File file : dir.listFiles()) {
// 处理每个文件(类文件)
processClassFile(file, classLoader);
}
}
}
// 初始化所有单例Bean(容器启动时创建)
createSingletonBeans();
}
2. 类文件处理逻辑
/**
* 处理单个类文件
* @param file 类文件对象
* @param classLoader 类加载器
*/
private void processClassFile(File file, ClassLoader classLoader) {
String fileName = file.getAbsolutePath();
// 只处理.class文件
if (fileName.endsWith(".class")) {
// 从绝对路径中提取完整类名(com\zhouyu\service\UserService -> com.zhouyu.service.UserService)
String className = fileName.substring(
fileName.indexOf("com"), // 从"com"开始
fileName.indexOf(".class") // 到".class"结束
).replace("\\", "."); // 替换路径分隔符
try {
// 加载类对象
Class<?> clazz = classLoader.loadClass(className);
// 检查是否有@Component注解
if (clazz.isAnnotationPresent(Component.class)) {
// 注册Bean定义到容器
registerBeanDefinition(clazz);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. Bean定义注册
/**
* 注册Bean定义到容器
* @param clazz 要注册的Class对象
*/
private void registerBeanDefinition(Class<?> clazz) {
// 获取@Component注解配置
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value();
// 创建Bean定义对象
BeanDefinition definition = new BeanDefinition();
definition.setType(clazz); // 设置Bean类型
// 检查是否有@Scope注解
if (clazz.isAnnotationPresent(Scope.class)) {
// 获取作用域配置
Scope scope = clazz.getAnnotation(Scope.class);
definition.setScope(scope.value());
} else {
// 默认单例模式
definition.setScope("singleton");
}
// 将Bean定义存入映射表
beanDefinitionMap.put(beanName, definition);
}
五、Bean创建与管理
1. 单例Bean预创建
/**
* 初始化所有单例Bean(在容器启动时创建)
*/
private void createSingletonBeans() {
// 遍历所有Bean定义
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition definition = beanDefinitionMap.get(beanName);
// 只处理单例Bean
if ("singleton".equals(definition.getScope())) {
// 创建Bean实例
Object bean = createBean(beanName, definition);
// 存入单例对象池
singletonObject.put(beanName, bean);
}
}
}
2. Bean实例化方法
/**
* 创建Bean实例
* @param beanName Bean名称
* @param definition Bean定义
* @return 创建的Bean实例
*/
private Object createBean(String beanName, BeanDefinition definition) {
Class clazz = definition.getType();
try {
// 通过默认构造器创建实例(反射机制)
return clazz.getConstructor().newInstance();
} catch (Exception e) {
// 封装创建异常
throw new RuntimeException("创建Bean失败: " + beanName, e);
}
}
3. getBean实现
/**
* 获取Bean实例的核心方法
* @param beanName 要获取的Bean名称
* @return Bean实例
* @throws NullPointerException 如果找不到Bean定义
*/
public Object getBean(String beanName) {
// 从Bean定义映射表获取元数据
BeanDefinition definition = beanDefinitionMap.get(beanName);
// 检查Bean定义是否存在
if (definition == null) {
throw new NullPointerException("未定义的Bean: " + beanName);
}
// 获取Bean的作用域配置
String scope = definition.getScope();
// 根据作用域类型返回Bean实例
if ("singleton".equals(scope)) {
// 单例模式:从单例池获取
Object bean = singletonObject.get(beanName);
// 双重检查:如果还未创建则创建并缓存
if (bean == null) {
bean = createBean(beanName, definition);
singletonObject.put(beanName, bean);
}
return bean;
} else {
// 原型模式:每次创建新实例
return createBean(beanName, definition);
}
}