杭州网站搜索排名vi设计网站有哪些
2026/4/3 5:37:10 网站建设 项目流程
杭州网站搜索排名,vi设计网站有哪些,wordpress媒体库 ftp,大同网站建设设计手写Spring IoC#xff1a;注解反射打造轻量级容器 深入理解Spring IoC核心原理#xff0c;通过注解和反射机制手写一个简易版IoC容器#xff0c;掌握依赖注入的本质。1. 引言#xff1a;Spring IoC的魔力 在Spring框架中#xff0c;IoC#xff08;控制反转#xff09;…手写Spring IoC注解反射打造轻量级容器深入理解Spring IoC核心原理通过注解和反射机制手写一个简易版IoC容器掌握依赖注入的本质。1. 引言Spring IoC的魔力在Spring框架中IoC控制反转和DI依赖注入是最核心的概念。只需一个Autowired注解Spring就能自动帮我们注入依赖对象这背后的原理是什么本文将通过注解反射的方式手写一个简易版Spring IoC容器让你深入理解注解是如何被扫描和解析的Bean是如何被创建和管理的依赖注入是如何实现的Spring容器的运行机制Spring IoC容器架构1.1 为什么要手写IoC理解原理- 知其然更知其所以然面试必备- Spring IoC是面试高频考点提升能力- 掌握反射、注解等核心技术框架选型- 理解框架设计思想2. 核心概念IoC、DI、注解、反射2.1 控制反转IoC传统方式对象自己创建依赖public class UserService { private UserDao userDao new UserDaoImpl(); // 主动创建 }IoC方式对象由容器创建和注入public class UserService { Autowired private UserDao userDao; // 被动接收 }控制反转就是把对象创建和依赖管理的控制权从应用代码转移到IoC容器。2.2 依赖注入DI依赖注入是IoC的实现方式有三种注入方式① 构造器注入Component public class UserService { private final UserDao userDao; Autowired public UserService(UserDao userDao) { this.userDao userDao; } }② Setter注入Component public class UserService { private UserDao userDao; Autowired public void setUserDao(UserDao userDao) { this.userDao userDao; } }③ 字段注入最常用Component public class UserService { Autowired private UserDao userDao; }2.3 Java注解注解是Java 5引入的元数据标记机制。// 定义注解 Retention(RetentionPolicy.RUNTIME) // 运行时保留 Target(ElementType.TYPE) // 作用于类 public interface Component { String value() default ; } // 使用注解 Component(userService) public class UserService { }2.4 Java反射反射允许程序在运行时动态获取类信息并操作对象。// 加载类 Class? clazz Class.forName(com.example.UserService); // 检查注解 if (clazz.isAnnotationPresent(Component.class)) { Component component clazz.getAnnotation(Component.class); String beanName component.value(); } // 创建实例 Object instance clazz.getDeclaredConstructor().newInstance(); // 获取字段 Field[] fields clazz.getDeclaredFields(); // 设置字段值 field.setAccessible(true); field.set(instance, value);3. 第一步定义核心注解Spring核心注解首先定义我们自己的注解模拟Spring的核心注解。3.1 Component注解package com.myspring.annotation; import java.lang.annotation.*; /** * 标记组件类类似Spring的Component */ Retention(RetentionPolicy.RUNTIME) Target(ElementType.TYPE) public interface Component { /** * Bean名称默认为类名首字母小写 */ String value() default ; }3.2 Autowired注解package com.myspring.annotation; import java.lang.annotation.*; /** * 自动注入依赖类似Spring的Autowired */ Retention(RetentionPolicy.RUNTIME) Target({ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR}) public interface Autowired { /** * 是否必须注入 */ boolean required() default true; }3.3 Qualifier注解package com.myspring.annotation; import java.lang.annotation.*; /** * 指定要注入的Bean名称 */ Retention(RetentionPolicy.RUNTIME) Target({ElementType.FIELD, ElementType.PARAMETER}) public interface Qualifier { String value(); }3.4 Scope注解package com.myspring.annotation; import java.lang.annotation.*; /** * 指定Bean的作用域 */ Retention(RetentionPolicy.RUNTIME) Target(ElementType.TYPE) public interface Scope { String value() default singleton; }4. 第二步实现包扫描器注解扫描 流程包扫描器负责扫描指定包下的所有类找出带有Component注解的类。4.1 ClassScanner类package com.myspring.core; import com.myspring.annotation.Component; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * 类扫描器扫描指定包下的所有类 */ public class ClassScanner { /** * 扫描指定包下带有Component注解的类 * * param basePackage 基础包路径如com.example * return 带有Component注解的Class列表 */ public static ListClass? scanComponents(String basePackage) { ListClass? classList new ArrayList(); try { // 将包名转换为路径 String packagePath basePackage.replace(., /); // 获取包的URL路径 ClassLoader classLoader Thread.currentThread().getContextClassLoader(); URL resource classLoader.getResource(packagePath); if (resource null) { System.out.println(包路径不存在: basePackage); return classList; } // 获取包的文件路径 File packageDir new File(resource.getFile()); // 递归扫描所有类文件 scanClasses(packageDir, basePackage, classList); } catch (Exception e) { e.printStackTrace(); } return classList; } /** * 递归扫描目录下的所有类文件 */ private static void scanClasses(File dir, String packageName, ListClass? classList) { if (!dir.exists() || !dir.isDirectory()) { return; } File[] files dir.listFiles(); if (files null) { return; } for (File file : files) { if (file.isDirectory()) { // 递归扫描子目录 scanClasses(file, packageName . file.getName(), classList); } else if (file.getName().endsWith(.class)) { try { // 获取类名 String className packageName . file.getName().replace(.class, ); // 加载类 Class? clazz Class.forName(className); // 检查是否有Component注解 if (clazz.isAnnotationPresent(Component.class)) { classList.add(clazz); System.out.println(扫描到组件: className); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } }5. 第三步创建Bean工厂Bean工厂负责存储和管理所有的Bean实例。5.1 BeanDefinition类package com.myspring.core; /** * Bean定义信息 */ public class BeanDefinition { private String beanName; private Class? beanClass; private String scope; private Object singletonInstance; public BeanDefinition(String beanName, Class? beanClass, String scope) { this.beanName beanName; this.beanClass beanClass; this.scope scope; } // Getter和Setter方法 public String getBeanName() { return beanName; } public Class? getBeanClass() { return beanClass; } public String getScope() { return scope; } public Object getSingletonInstance() { return singletonInstance; } public void setSingletonInstance(Object instance) { this.singletonInstance instance; } }5.2 BeanFactory类package com.myspring.core; import com.myspring.annotation.Component; import com.myspring.annotation.Scope; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Bean工厂创建和管理Bean实例 */ public class BeanFactory { // 存储Bean定义信息 private MapString, BeanDefinition beanDefinitionMap new ConcurrentHashMap(); /** * 注册Bean定义 */ public void registerBeanDefinition(Class? clazz) { // 获取Bean名称 Component component clazz.getAnnotation(Component.class); String beanName component.value(); if (beanName.isEmpty()) { // 默认使用类名首字母小写 beanName toLowerFirstCase(clazz.getSimpleName()); } // 获取作用域 String scope singleton; if (clazz.isAnnotationPresent(Scope.class)) { Scope scopeAnnotation clazz.getAnnotation(Scope.class); scope scopeAnnotation.value(); } // 创建BeanDefinition并注册 BeanDefinition beanDefinition new BeanDefinition(beanName, clazz, scope); beanDefinitionMap.put(beanName, beanDefinition); System.out.println(注册Bean: beanName , 作用域: scope); } /** * 获取Bean实例 */ public Object getBean(String beanName) { BeanDefinition beanDefinition beanDefinitionMap.get(beanName); if (beanDefinition null) { throw new RuntimeException(Bean不存在: beanName); } // 单例模式 if (singleton.equals(beanDefinition.getScope())) { Object instance beanDefinition.getSingletonInstance(); if (instance null) { instance createBean(beanDefinition); beanDefinition.setSingletonInstance(instance); } return instance; } // 原型模式每次都创建新实例 return createBean(beanDefinition); } /** * 根据类型获取Bean */ public Object getBean(Class? clazz) { for (BeanDefinition bd : beanDefinitionMap.values()) { if (clazz.isAssignableFrom(bd.getBeanClass())) { return getBean(bd.getBeanName()); } } throw new RuntimeException(Bean不存在: clazz.getName()); } /** * 创建Bean实例 */ private Object createBean(BeanDefinition beanDefinition) { try { Class? clazz beanDefinition.getBeanClass(); Object instance clazz.getDeclaredConstructor().newInstance(); System.out.println(创建Bean实例: beanDefinition.getBeanName()); return instance; } catch (Exception e) { throw new RuntimeException(创建Bean失败: beanDefinition.getBeanName(), e); } } /** * 首字母小写 */ private String toLowerFirstCase(String str) { char[] chars str.toCharArray(); chars[0] 32; return String.valueOf(chars); } /** * 获取所有Bean名称 */ public MapString, BeanDefinition getBeanDefinitions() { return beanDefinitionMap; } }6. 第四步实现依赖注入依赖注入流程依赖注入是IoC容器的核心功能通过反射自动为Bean注入依赖。6.1 DependencyInjector类package com.myspring.core; import com.myspring.annotation.Autowired; import com.myspring.annotation.Qualifier; import java.lang.reflect.Field; /** * 依赖注入器为Bean注入依赖 */ public class DependencyInjector { private BeanFactory beanFactory; public DependencyInjector(BeanFactory beanFactory) { this.beanFactory beanFactory; } /** * 为所有Bean执行依赖注入 */ public void injectDependencies() { for (BeanDefinition bd : beanFactory.getBeanDefinitions().values()) { Object bean beanFactory.getBean(bd.getBeanName()); injectBean(bean); } } /** * 为单个Bean注入依赖 */ public void injectBean(Object bean) { Class? clazz bean.getClass(); // 获取所有字段 Field[] fields clazz.getDeclaredFields(); for (Field field : fields) { // 检查是否有Autowired注解 if (!field.isAnnotationPresent(Autowired.class)) { continue; } Autowired autowired field.getAnnotation(Autowired.class); try { // 确定要注入的Bean Object dependency null; // 检查是否有Qualifier指定Bean名称 if (field.isAnnotationPresent(Qualifier.class)) { Qualifier qualifier field.getAnnotation(Qualifier.class); String beanName qualifier.value(); dependency beanFactory.getBean(beanName); } else { // 根据类型查找Bean dependency beanFactory.getBean(field.getType()); } // 反射设置字段值 field.setAccessible(true); field.set(bean, dependency); System.out.println(注入依赖: clazz.getSimpleName() . field.getName()); } catch (Exception e) { if (autowired.required()) { throw new RuntimeException(依赖注入失败: clazz.getSimpleName() . field.getName(), e); } } } } }7. 第五步完善生命周期Bean生命周期7.1 生命周期注解package com.myspring.annotation; import java.lang.annotation.*; /** * Bean初始化后调用 */ Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) public interface PostConstruct { } package com.myspring.annotation; import java.lang.annotation.*; /** * Bean销毁前调用 */ Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) public interface PreDestroy { }7.2 生命周期管理器package com.myspring.core; import com.myspring.annotation.PostConstruct; import com.myspring.annotation.PreDestroy; import java.lang.reflect.Method; /** * Bean生命周期管理器 */ public class LifecycleManager { /** * 执行初始化方法 */ public static void invokeInitMethod(Object bean) { Class? clazz bean.getClass(); Method[] methods clazz.getDeclaredMethods(); for (Method method : methods) { if (method.isAnnotationPresent(PostConstruct.class)) { try { method.setAccessible(true); method.invoke(bean); System.out.println(执行初始化方法: clazz.getSimpleName() . method.getName()); } catch (Exception e) { throw new RuntimeException(初始化方法执行失败, e); } } } } /** * 执行销毁方法 */ public static void invokeDestroyMethod(Object bean) { Class? clazz bean.getClass(); Method[] methods clazz.getDeclaredMethods(); for (Method method : methods) { if (method.isAnnotationPresent(PreDestroy.class)) { try { method.setAccessible(true); method.invoke(bean); System.out.println(执行销毁方法: clazz.getSimpleName() . method.getName()); } catch (Exception e) { e.printStackTrace(); } } } } }8. 完整示例使用手写IoC手写IoC实现步骤8.1 创建ApplicationContextpackage com.myspring.core; import java.util.List; /** * 应用上下文整合所有功能 */ public class ApplicationContext { private BeanFactory beanFactory; private DependencyInjector injector; public ApplicationContext(String basePackage) { // 1. 创建Bean工厂 beanFactory new BeanFactory(); // 2. 扫描组件 System.out.println( 开始扫描组件 ); ListClass? componentClasses ClassScanner.scanComponents(basePackage); // 3. 注册Bean定义 System.out.println(\n 注册Bean定义 ); for (Class? clazz : componentClasses) { beanFactory.registerBeanDefinition(clazz); } // 4. 实例化所有单例Bean System.out.println(\n 实例化单例Bean ); for (BeanDefinition bd : beanFactory.getBeanDefinitions().values()) { if (singleton.equals(bd.getScope())) { beanFactory.getBean(bd.getBeanName()); } } // 5. 依赖注入 System.out.println(\n 执行依赖注入 ); injector new DependencyInjector(beanFactory); injector.injectDependencies(); // 6. 执行初始化方法 System.out.println(\n 执行初始化方法 ); for (BeanDefinition bd : beanFactory.getBeanDefinitions().values()) { Object bean beanFactory.getBean(bd.getBeanName()); LifecycleManager.invokeInitMethod(bean); } System.out.println(\n IoC容器启动完成 \n); } /** * 获取Bean */ public Object getBean(String beanName) { return beanFactory.getBean(beanName); } /** * 根据类型获取Bean */ public T T getBean(ClassT clazz) { return (T) beanFactory.getBean(clazz); } /** * 关闭容器 */ public void close() { System.out.println(\n 关闭IoC容器 ); for (BeanDefinition bd : beanFactory.getBeanDefinitions().values()) { Object bean beanFactory.getBean(bd.getBeanName()); LifecycleManager.invokeDestroyMethod(bean); } } }8.2 编写测试类package com.example.dao; import com.myspring.annotation.Component; Component public class UserDao { public void save() { System.out.println(UserDao: 保存用户数据); } } package com.example.service; import com.example.dao.UserDao; import com.myspring.annotation.Autowired; import com.myspring.annotation.Component; import com.myspring.annotation.PostConstruct; import com.myspring.annotation.PreDestroy; Component public class UserService { Autowired private UserDao userDao; public void register(String username) { System.out.println(UserService: 注册用户 username); userDao.save(); } PostConstruct public void init() { System.out.println(UserService初始化完成); } PreDestroy public void destroy() { System.out.println(UserService准备销毁); } } package com.example; import com.example.service.UserService; import com.myspring.core.ApplicationContext; /** * 测试类 */ public class Main { public static void main(String[] args) { // 创建IoC容器 ApplicationContext context new ApplicationContext(com.example); // 获取Bean并使用 UserService userService context.getBean(UserService.class); userService.register(张三); // 关闭容器 context.close(); } }8.3 运行输出 开始扫描组件 扫描到组件: com.example.dao.UserDao 扫描到组件: com.example.service.UserService 注册Bean定义 注册Bean: userDao, 作用域: singleton 注册Bean: userService, 作用域: singleton 实例化单例Bean 创建Bean实例: userDao 创建Bean实例: userService 执行依赖注入 注入依赖: UserService.userDao 执行初始化方法 执行初始化方法: UserService.init UserService初始化完成 IoC容器启动完成 UserService: 注册用户 张三 UserDao: 保存用户数据 关闭IoC容器 执行销毁方法: UserService.destroy UserService准备销毁9. 总结9.1 核心要点通过手写IoC容器我们深入理解了注解机制- 使用Retention、Target定义注解反射技术- 类加载、实例创建、字段注入扫描解析- 递归扫描包路径解析注解信息Bean管理- 单例/原型模式Bean定义存储依赖注入- 自动查找和注入依赖对象生命周期- 初始化和销毁回调方法9.2 与Spring IoC的对比功能手写版本Spring IoC注解扫描简单递归高性能ASM字节码扫描Bean管理Map存储多级缓存循环依赖处理依赖注入字段注入字段构造器Setter作用域singleton/prototype更多作用域AOP支持无完整AOP框架性能优化基础大量优化策略

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询