Spring源码分析之IOC 容器
Spring启动方式:
启动spring容器有两种方式,分别是通过配置文件的读取启动,通过JavaConfig配置类启动。
在使用配置文件启动的时候,我们就需要使用ClassPathXmlApplicationContext("xx.xml")来构建容器,并初始化bean。
1 public class Test1 { 2 public static void main(String[] args) { 3 ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); 4 IndexService service = (IndexService) context.getBean("service"); 5 service.query(); 6 } 7 }
在使用JavaConfig配置类启动的时候,我们需要使用AnnotationConfigApplicationContext("xx.class")来构建容器,并初始化bean。
1 public class Test { 2 public static void main(String[] args) { 3 //把spring所有的前提环境准备好了,包括spring容器还有类的实例化都完成了。 4 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyAnnotation.class); 5 IndexService service = (IndexService)context.getBean("service"); 6 service.query(); 7 } 8 }
进入AnnotationConfigApplicationContext类中,查看构造方法。
1 /** 2 * 这个构造方法需要传入一个被Javaconfig注解过的配置类 3 * 然后会把这个被注解了的配置类通过注解读取器读取后进行解析 4 * @param annotatedClasses 5 */ 6 public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { 7 //这里由于它有父类,故而会先调用父类的构造方法,然后才会调用自己的构造方法, 8 //在自己的构造方法中初始化一个读取器和扫描器 9 this(); 10 //注册单个bean给容器,比如有新加的类可以使用这个方法 11 //但是注册之后需要手动调用refresh()方法去触发容器解析注解 12 register(annotatedClasses); 13 refresh(); 14 }
进入this()方法,查看自己的构造方法
1 public AnnotationConfigApplicationContext() { 2 /** 3 * 创建一个读取注解的Bean定义读取器 4 * 什么是Bean定义?BeanDefinition 5 * BeanDefinition这个类是描述springBean对象的类。 6 */ 7 this.reader = new AnnotatedBeanDefinitionReader(this); 8 /** 9 * 创建一个扫描器,扫描所有加了注解的类 10 */ 11 this.scanner = new ClassPathBeanDefinitionScanner(this); 12 }
进入register()方法,忽略掉封装方法,直接进入AnnotatedBeanDefinitionReader类中的doRegisterBean()方法:
1 <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, 2 @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) { 3 4 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); 5 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { 6 return; 7 } 8 9 abd.setInstanceSupplier(instanceSupplier); 10 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); 11 abd.setScope(scopeMetadata.getScopeName()); 12 String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); 13 14 AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); 15 /** 16 * 对属性进行判断 17 */ 18 if (qualifiers != null) { 19 for (Class<? extends Annotation> qualifier : qualifiers) { 20 if (Primary.class == qualifier) { 21 abd.setPrimary(true); 22 } 23 else if (Lazy.class == qualifier) { 24 abd.setLazyInit(true); 25 } 26 else { 27 abd.addQualifier(new AutowireCandidateQualifier(qualifier)); 28 } 29 } 30 } 31 for (BeanDefinitionCustomizer customizer : definitionCustomizers) { 32 customizer.customize(abd); 33 } 34 35 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); 36 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); 37 /** 38 * 把处理后的bean当做参数,进行注册 39 */ 40 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); 41 }
进入BeanDefinitionReaderUtils类中的registerBeanDefinition()方法:
1 /** 2 * 向给定的bean工厂注册给定的bean定义 3 * @param definitionHolder 4 * @param registry 5 * @throws BeanDefinitionStoreException 6 */ 7 public static void registerBeanDefinition( 8 BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) 9 throws BeanDefinitionStoreException { 10 11 // Register bean definition under primary name. 12 // 把beanName作为主名,在bean工厂中注册 13 String beanName = definitionHolder.getBeanName(); 14 //通过DefaultListableBeanFactory工厂进行注册 15 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); 16 17 // Register aliases for bean name, if any. 18 // 对别名进行处理 19 String[] aliases = definitionHolder.getAliases(); 20 if (aliases != null) { 21 for (String alias : aliases) { 22 registry.registerAlias(beanName, alias); 23 } 24 } 25 }
进入DefaultListableBeanFactory类的registerBeanDefinition()方法进行注册。
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
1 @Override 2 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 3 throws BeanDefinitionStoreException { 4 5 Assert.hasText(beanName, "Bean name must not be empty"); 6 Assert.notNull(beanDefinition, "BeanDefinition must not be null"); 7 8 if (beanDefinition instanceof AbstractBeanDefinition) { 9 try { 10 ((AbstractBeanDefinition) beanDefinition).validate(); 11 } 12 catch (BeanDefinitionValidationException ex) { 13 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, 14 "Validation of bean definition failed", ex); 15 } 16 } 17 18 BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); 19 if (existingDefinition != null) { 20 if (!isAllowBeanDefinitionOverriding()) { 21 throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); 22 } 23 else if (existingDefinition.getRole() < beanDefinition.getRole()) { 24 // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE 25 if (logger.isInfoEnabled()) { 26 logger.info("Overriding user-defined bean definition for bean '" + beanName + 27 "' with a framework-generated bean definition: replacing [" + 28 existingDefinition + "] with [" + beanDefinition + "]"); 29 } 30 } 31 else if (!beanDefinition.equals(existingDefinition)) { 32 if (logger.isDebugEnabled()) { 33 logger.debug("Overriding bean definition for bean '" + beanName + 34 "' with a different definition: replacing [" + existingDefinition + 35 "] with [" + beanDefinition + "]"); 36 } 37 } 38 else { 39 if (logger.isTraceEnabled()) { 40 logger.trace("Overriding bean definition for bean '" + beanName + 41 "' with an equivalent definition: replacing [" + existingDefinition + 42 "] with [" + beanDefinition + "]"); 43 } 44 } 45 this.beanDefinitionMap.put(beanName, beanDefinition); 46 } 47 else { 48 if (hasBeanCreationStarted()) { 49 // Cannot modify startup-time collection elements anymore (for stable iteration) 50 synchronized (this.beanDefinitionMap) { 51 this.beanDefinitionMap.put(beanName, beanDefinition); 52 List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); 53 updatedDefinitions.addAll(this.beanDefinitionNames); 54 updatedDefinitions.add(beanName); 55 this.beanDefinitionNames = updatedDefinitions; 56 if (this.manualSingletonNames.contains(beanName)) { 57 Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); 58 updatedSingletons.remove(beanName); 59 this.manualSingletonNames = updatedSingletons; 60 } 61 } 62 } 63 else { 64 // Still in startup registration phase 65 this.beanDefinitionMap.put(beanName, beanDefinition); 66 this.beanDefinitionNames.add(beanName); 67 this.manualSingletonNames.remove(beanName); 68 } 69 this.frozenBeanDefinitionNames = null; 70 } 71 72 if (existingDefinition != null || containsSingleton(beanName)) { 73 resetBeanDefinition(beanName); 74 } 75 }
到这里,bean注册完成了,然后调用refresh()方法进行实例化。
1 @Override 2 public void refresh() throws BeansException, IllegalStateException { 3 synchronized (this.startupShutdownMonitor) { 4 // Prepare this context for refreshing. 5 // 准备工作,包括设置启动时间,是否激活标识位, 6 // 初始化属性源(property source)设置 7 prepareRefresh(); 8 9 // Tell the subclass to refresh the internal bean factory. 10 // 通过子类来获取之前注册了bean的容器工厂beanFactory 11 // 这里我们是获得DefaultListableBeanFactory这个工厂类 12 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 13 14 // Prepare the bean factory for use in this context. 15 prepareBeanFactory(beanFactory); 16 17 try { 18 // Allows post-processing of the bean factory in context subclasses. 19 postProcessBeanFactory(beanFactory); 20 21 // Invoke factory processors registered as beans in the context. 22 invokeBeanFactoryPostProcessors(beanFactory); 23 24 // Register bean processors that intercept bean creation. 25 registerBeanPostProcessors(beanFactory); 26 27 // Initialize message source for this context. 28 initMessageSource(); 29 30 // Initialize event multicaster for this context. 31 initApplicationEventMulticaster(); 32 33 // Initialize other special beans in specific context subclasses. 34 onRefresh(); 35 36 // Check for listener beans and register them. 37 registerListeners(); 38 39 // Instantiate all remaining (non-lazy-init) singletons. 40 finishBeanFactoryInitialization(beanFactory); 41 42 // Last step: publish corresponding event. 43 finishRefresh(); 44 } 45 46 catch (BeansException ex) { 47 if (logger.isWarnEnabled()) { 48 logger.warn("Exception encountered during context initialization - " + 49 "cancelling refresh attempt: " + ex); 50 } 51 52 // Destroy already created singletons to avoid dangling resources. 53 destroyBeans(); 54 55 // Reset 'active' flag. 56 cancelRefresh(ex); 57 58 // Propagate exception to caller. 59 throw ex; 60 } 61 62 finally { 63 // Reset common introspection caches in Spring's core, since we 64 // might not ever need metadata for singleton beans anymore... 65 resetCommonCaches(); 66 } 67 } 68 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· Blazor Hybrid适配到HarmonyOS系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 分享4款.NET开源、免费、实用的商城系统
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库