摘要:主要过程为调用自身的另一个有参构造器此处的即为本身此处的最终返回一个调用无参构造器创建出来的对象参数非空效验保存创建一个用于注解解析器,后面会用到注册需要用到的顾名思义,即为所处的环境,包括配置的读取等。
零 前期准备 0 FBI WARNING
文章异常啰嗦且绕弯。
1 版本spring版本 : spring 5.1.2.RELEASE
IDE : idea 2018.3
2 Bean Demopackage ioc; /** * java bean */ public class Person { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }3 Config Demo
package ioc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 配置类 */ @Configuration public class IocConfig { /** * 用代码配置方式注入一个bean */ @Bean(name = "person") public Person getPerson(){ Person person = new Person(); person.setAge(100); person.setName("张三"); return person; } }4 main方法
package ioc; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class IocTest { public static void main(String[] args){ ApplicationContext context = new AnnotationConfigApplicationContext(IocConfig.class); Person person = (Person) context.getBean("person"); System.out.println(person.getName() + " , " + person.getAge()); } }一 项目的启动和Bean的注入 1 总览
Spring 的初始化被封装在这行代码中:
ApplicationContext context = new AnnotationConfigApplicationContext(IocConfig.class);
这个构造器方法内部有三行代码:
public AnnotationConfigApplicationContext(Class>... annotatedClasses) { this(); // 2 无参构造器 register(annotatedClasses); // 3 reader 注册配置类 refresh(); // 4 在 bean factory 中创造 bean }2 无参构造器
该 part 的起点为 AnnotationConfigApplicationContext 调用自身的无参构造器:
//AnnotationConfigApplicationContext.class public AnnotationConfigApplicationContext(Class>... annotatedClasses) { this(); // 2 无参构造器 register(annotatedClasses); refresh(); }
追踪无参构造器:
//AnnotationConfigApplicationContext.class public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); //2.1 this.scanner = new ClassPathBeanDefinitionScanner(this); //2.5 }
AnnotatedBeanDefinitionReader 创建的过程中会将 Spring 自身需要的 bean 和配置用的 bean 注册到 bean factory 中。
【ClassPathBeanDefinitionScanner 本例中暂时用不到,不做详细分析,只简单看一下构造方法】
AnnotationConfigApplicationContext 的父类 GenericApplicationContext 会在无参构造器中创建一个 DefaultListableBeanFactory ,也就是本例中的 bean factory:
//GenericApplicationContext.class public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }
DefaultListableBeanFactory 内部会维护了多个 ConcurrentHashMap 对象,用于分门别类地保存 bean。
最主要的一个 map 对象是 singletonObjects。这个对象被定义在 DefaultSingletonBeanRegistry 中,用于存放所有的单例 bean:
//DefaultSingletonBeanRegistry.class private final Map2.1singletonObjects = new ConcurrentHashMap<>(256);
AnnotatedBeanDefinitionReader 创建的过程中将 spring 需要的几个 processor bean 注册到 DefaultListableBeanFactory 中。主要过程为:
//AnnotatedBeanDefinitionReader.class public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { //调用自身的另一个有参构造器 //此处的 registry 即为 AnnotationConfigApplicationContext 本身 //此处的 getOrCreateEnvironment(registry) 最终返回一个调用 StandardEnvironment 无参构造器创建出来的对象 this(registry, getOrCreateEnvironment(registry)); } //AnnotatedBeanDefinitionReader.class public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { //参数非空效验 Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); //保存 AnnotationConfigApplicationContext this.registry = registry; //创建一个用于注解解析器,后面会用到 this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); //注册 Spring 需要用到的 processor bean AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }
Environment 顾名思义,即为 Spring 所处的环境,包括 properties 配置的读取等。本例中暂时没有用到,按下不表。
上述代码的核心是调用 AnnotationConfigUtils 的 registerAnnotationConfigProcessors(...) 方法,继续追踪:
//AnnotationConfigUtils.class public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { registerAnnotationConfigProcessors(registry, null); } //AnnotationConfigUtils.class public static SetregisterAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { //获取 bean factory DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); //以下代码设置了 beanFactory 的两个内部对象,暂时不展开 if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } //新建一个集合,用于在方法末尾返回所有注册的 bean 的包装类,但是实际上本例中没有接收返回值,所以可以忽略 Set beanDefs = new LinkedHashSet<>(8); //判断 bean factory 中是否存在这个名称的 bean,如果不存在就注册一个,以下雷同 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { //将要注册的 processor class 包装成一个 BeanDefinition RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); //本例中 source 为 null def.setSource(source); //注册 bean,并添加到集合中 beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } //jsr250Present 与 jpaPresent 均为 boolean 类型的变量 //jsr250Present 的意思是检查是否对 JSR-250 标准进行支持,jpaPresent 的意思是检查是否对 JPA 标准进行支持 //目前 Spring 支持 JSR-250 标准,不支持 JPA 标准 if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); }catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } //返回上述的集合 return beanDefs; }
该方法中主体代码都是雷同的,即为:
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { //将要注册的 processor class 包装成一个 BeanDefinition RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); //本例中 source 为 null def.setSource(source); //注册 bean ,并添加到集合中 beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); }
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME : org.springframework.context.annotation.internalConfigurationAnnotationProcessor CONFIGURATION_BEAN_NAME_GENERATOR : org.springframework.context.annotation.internalConfigurationBeanNameGenerator AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME : org.springframework.context.annotation.internalAutowiredAnnotationProcessor COMMON_ANNOTATION_PROCESSOR_BEAN_NAME : org.springframework.context.annotation.internalCommonAnnotationProcessor PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME : org.springframework.context.annotation.internalPersistenceAnnotationProcessor PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME : org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor EVENT_LISTENER_PROCESSOR_BEAN_NAME : org.springframework.context.event.internalEventListenerProcessor EVENT_LISTENER_FACTORY_BEAN_NAME : org.springframework.context.event.internalEventListenerFactory
这些常量都是 spring 中类的路径和名称。
registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)
此行代码会通过 AnnotationConfigApplicationContext 调用到 DefaultListableBeanFactory 内部的 beanDefinitionMap 对象,最终查询到这个 bean 对象是否已经被注册。如果不存在,则执行下方的注册操作。
beanDefinitionMap 是 DefaultListableBeanFactory 内部存放所有已经注册了的 bean 的信息的 ConcurrentHashMap 对象,后面会经常提到。
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
RootBeanDefinition 是 BeanDefinition 的实现类。BeanDefinition 是 Spring 中 bean 的描述包装接口,用于保存 bean 的各类信息,包括且不限于 bean 的名称、父类、注解、是否惰性加载等属性。
SetbeanDefs = new LinkedHashSet<>(8);
BeanDefinitionHolder 是 BeanDefinition 的支持类,内部存储了 BeanDefinition 、bean name 、bean aliases(别名)。
【在 Spring 的 bean 注册过程中,有多次 BeanDefinition 和 BeanDefinitionHolder 的包装和解包装操作,具体有待学习】
registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)
起主要作用的是上面这行代码。追踪这个方法的实现:
//AnnotationConfigUtils.class private static BeanDefinitionHolder registerPostProcessor( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) { //bean 的角色定义 //BeanDefinition.ROLE_INFRASTRUCTURE = 2 definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); //调用 AnnotationConfigApplicationContext 的 registerBeanDefinition 方法 registry.registerBeanDefinition(beanName, definition); //返回一个封装类 return new BeanDefinitionHolder(definition, beanName); }
BeanDefinition 的 role 是指该 bean 在 Spring 中的角色定义。对于 Spring 注册进去的 processor bean,定义值均为 2,意思是 infrastructure(基础设施)。
除此以外角色定义还有 application(应用) 和 support(支持)。
AnnotationConfigApplicationContext 内部其实没有 registerBeanDefinition(...) 这个方法,而是继承自 GenericApplicationContext:
//GenericApplicationContext.class public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { //2.2 this.beanFactory.registerBeanDefinition(beanName, beanDefinition); }
此方法实际上调用了 DefaultListableBeanFactory 的 registerBeanDefinition(...) 方法进行 bean 的注册。
2.2继续追踪方法的内部实现:
//DefaultListableBeanFactory.class public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { //参数非空验证 Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); //bean 的有效性验证 if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } //beanDefinitionMap 为存储所有注册 bean 信息的 map 对象 //正常情况下此处获取的应该是 null 值,即该 bean 的信息还未注册 BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); if (existingDefinition != null) { //如果 bean 已经存在于 map 中,则需要判断是否允许重写 bean definition if (!isAllowBeanDefinitionOverriding()) { //不允许,抛出异常 throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); }else if (existingDefinition.getRole() < beanDefinition.getRole()) { if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean "" + beanName + "" with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } }else if (!beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean "" + beanName + "" with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } }else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean "" + beanName + "" with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } //只要设置为允许重写,就会在最后更新 map,只是记录的 log 内容会不同 this.beanDefinitionMap.put(beanName, beanDefinition); }else { //正常情况下 if (hasBeanCreationStarted()) { //2.3 synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); ListupdatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if (this.manualSingletonNames.contains(beanName)) { Set updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } }else { //将 bean 注册入 beanDefinitionMap 中 this.beanDefinitionMap.put(beanName, beanDefinition); //将 bean name 添加入 beanDefinitionNames 中 this.beanDefinitionNames.add(beanName); //将 bean name 从 manualSingletonNames 中删除 this.manualSingletonNames.remove(beanName); } //清空数组 this.frozenBeanDefinitionNames = null; } //2.4 if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
先来关注这行代码:
((AbstractBeanDefinition) beanDefinition).validate();
追踪一下这行代码:
//AbstractBeanDefinition.class public void validate() throws BeanDefinitionValidationException { if (hasMethodOverrides() && getFactoryMethodName() != null) { throw new BeanDefinitionValidationException( "Cannot combine static factory method with method overrides: " + "the static factory method must create the instance"); } if (hasBeanClass()) { //此方法内部也主要用到了 hasMethodOverrides() ,这里暂时忽略该方法 prepareMethodOverrides(); } }
这个方法内部使用了 AbstractBeanDefinition 内定义的 hasMethodOverrides() 和 getFactoryMethodName() 方法去判断 beanDefinition 是否有效。同时满足这两个条件则会抛出异常。
根据官方文档的描述,hasMethodOverrides() 为如果 bean factory 重写了 bean 内的方法,就会返回 true;getFactoryMethodName() 为如果存在工厂方法就会返回该方法的名称。
【没有特别理解这几个方法的应用场景,根据网上资料来看,应该和 bean 的反射创建有一些关系】
再来关注这行代码:
this.frozenBeanDefinitionNames = null;
frozenBeanDefinitionNames 是定义在 DefaultListableBeanFactory 中的一个字符串数组,Spring 在完成 bean 注册之后会将 beanDefinitionNames 转成一个数组,并赋值给 frozenBeanDefinitionNames。
【此为 Spring 的一个内存优化操作】
2.3看一下上述方法的片段:
if (hasBeanCreationStarted()) { synchronized (this.beanDefinitionMap) { //线程锁 //执行注册操作 this.beanDefinitionMap.put(beanName, beanDefinition); //用一个新的 list 去替换原来的 ListupdatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; //检查单例 bean 名称集合 if (this.manualSingletonNames.contains(beanName)) { Set updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } }
先来追踪一下 hasBeanCreationStarted() 这个方法的内部实现:
//AbstractBeanFactory.class protected boolean hasBeanCreationStarted() { return !this.alreadyCreated.isEmpty(); }
alreadyCreated 是一个定义在 AbstractBeanFactory 中的集合,用于存放所有已经被创建(不是注册,是创建)的 bean 的名字。在创建和获取 bean 的时候都会去检查该集合。
在 processors bean 和 iocConfig bean 的注册阶段,该集合为空,此方法返回 false。但是要注意,在 person bean 的注册阶段,此时 iocConfig bean 已经被创建出来了,所以此集合是非空的,此方法返回 true。
//创建新列表 ListupdatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); //老列表被整个添加到新列表中 updatedDefinitions.addAll(this.beanDefinitionNames); //添加 beanName 到新列表中 updatedDefinitions.add(beanName); //替换 this.beanDefinitionNames = updatedDefinitions;
beanDefinitionNames 是一个定义在 DefaultListableBeanFactory 中的列表,用来存放所有注册的 bean 的名字。
if (this.manualSingletonNames.contains(beanName)) { //新建一个集合,并且将 manualSingletonNames 集合放入新集合中 SetupdatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); //删除这个 bean name updatedSingletons.remove(beanName); //替换 this.manualSingletonNames = updatedSingletons; }
manualSingletonNames 是一个定义在 DefaultListableBeanFactory 中的集合,用来存放已经被创建的单例 bean 的名字。因为是单例的,所以不允许重名 bean 的存在,这可能也是 Spring 这里使用集合的原因。
【Spring 的对于内存的优化精确到了每一个列表和集合的容量大小】
进入这个 if 判断条件的情况下,必然是这个 bean 还没有被创建,所以如果这个 bean 已经被放在在这个集合里,就需要删除。正常情况下 bean 的注册过程应该都不会进入执行这个代码片段。
2.4看一下上述方法的片段:
if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); }
判断条件中的 existingDefinition 是上方定义的一个 BeanDefinition :
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
一般来说等于 null。
而 containsSingleton(...) 方法具体的实现是在 DefaultSingletonBeanRegistry 中:
//DefaultSingletonBeanRegistry.class public boolean containsSingleton(String beanName) { return this.singletonObjects.containsKey(beanName); }
上面文章中提到过,singletonObjects 是最终保存单例 bean 的 map 对象。
综合来看就是此判断条件可以理解为:如果该 bean 已经注册或者已经被创建,则返回 true,若均未则返回 false。所以一般正常的注册流程是不会执行 resetBeanDefinition(...) 方法的。
关于 resetBeanDefinition(...) 方法,不展开讲了,大致来说就是此方法内部会重新去创建该 bean。
到此为止,reader 已经创建完毕,并且 Spring 使用到的 processors 也已经注册完毕。DefaultListableBeanFactory.registerBeanDefinition 方法非常重要,后面 config bean 和 person bean 的注册也是使用这个方法。
2.5回到原点:
//AnnotationConfigApplicationContext.class public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); //2.4 }
本例中暂时没有用到 ClassPathBeanDefinitionScanner,因为没有扫描包路径的方式去获取 bean。所以此处略讲一下 ClassPathBeanDefinitionScanner 的创建。
其构造方法有多层调用,最终的逻辑代码如下:
//ClassPathBeanDefinitionScanner.class public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) { //参数非空效验 Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //此处的 registry 是 AnnotationConfigApplicationContext this.registry = registry; //Spring 扫描包路径的过滤策略 //useDefaultFilters = true if (useDefaultFilters) { registerDefaultFilters(); } //存入环境对象,此处一个使用无参构造器创建出来的 StandardEnvironment 对象 setEnvironment(environment); //存入 resourceLoader,此处为 AnnotationConfigApplicationContext setResourceLoader(resourceLoader); }
【暂时不展开了】
To Be Continued ...文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/72608.html
摘要:顾名思义,其主要作用是解析标签。本例中没有用到上述的注解,所以均为。继续追踪这行代码的内部实现获取的名称调用的方法注册过程见处理的别名,本例中没有别名,不进入循环的具体内容有待研究,不展开。到此为止,已经被注册到中。 接上篇 3 reader 注册配置类 该 part 的起点: public AnnotationConfigApplicationContext(Class... ann...
摘要:为何重拾使用了多年,但是对其底层的一些实现还是一知半解,一些概念比较模糊故决定重新拾起,加深对的认识。小结是在完成创建后对其进行后置处理的接口是在完成实例化对其进行的后置处理接口是框架底层的核心接口,其提供了创建,获取等核心功能。 为何重拾 使用了 Spring 多年,但是对其底层的一些实现还是一知半解,一些概念比较模糊;故决定重新拾起,加深对 Spring 的认识。 重拾计划 spr...
摘要:何为简单点来定义就是切面,是一种编程范式。定义一个切面的载体定义一个切点定义一个为,并指定对应的切点一个注册配置类,启动容器,初始化时期获取对象,获取对象时期,并进行打印好了,这样我们整体的代理就已经完成。 问题:Spring AOP代理中的运行时期,是在初始化时期织入还是获取对象时期织入? 织入就是代理的过程,指目标对象进行封装转换成代理,实现了代理,就可以运用各种代理的场景模式。 ...
摘要:前言以下源码基于版本解析。实现源码分析对于的实现,总结来说就是定位加载和注册。定位就是需要定位配置文件的位置,加载就是将配置文件加载进内存注册就是通过解析配置文件注册。下面我们从其中的一种使用的方式一步一步的分析的实现源码。 前言 以下源码基于Spring 5.0.2版本解析。 什么是IOC容器? 容器,顾名思义可以用来容纳一切事物。我们平常所说的Spring IOC容器就是一个可以容...
摘要:概述约定大于配置的功力让我们如沐春风,在我之前写的文章从到也对比过和这两个框架,不过最终以超高的代码信噪比和易上手性让我们映像颇深。至于,我想在非时代大家应该不陌生吧,作用是配置容器,也即形式的容器的配置类所使用。 showImg(https://segmentfault.com/img/remote/1460000015822144); 概 述 SpringBoot 约定大于配置...
阅读 901·2021-11-22 12:09
阅读 3685·2021-09-27 13:36
阅读 1374·2021-08-20 09:37
阅读 3913·2019-12-27 12:22
阅读 2327·2019-08-30 15:55
阅读 2295·2019-08-30 13:16
阅读 2797·2019-08-26 17:06
阅读 3417·2019-08-23 18:32