(Depending on the bean definition, the factory will return either an independent instance of a contained object (the Prototype design pattern), or a single shared instance)
分层的BeanFactory,当请求对象实例时,先在当前BeanFactory中找,如果没有,就去父工厂中找
按照这个原理,当前工厂中的实例会覆盖夫工厂中的同名实例
-
BeanNameAware’s setBeanName
-
BeanClassLoaderAware’s setBeanClassLoader
-
BeanFactoryAware’s setBeanFactory
-
EnvironmentAware’s setEnvironment
-
EmbeddedValueResolverAware’s setEmbeddedValueResolver
-
ResourceLoaderAware’s setResourceLoader (only applicable when running in an application context)
-
ApplicationEventPublisherAware’s setApplicationEventPublisher (only applicable when running in an application context)
-
MessageSourceAware’s setMessageSource (only applicable when running in an application context)
-
ApplicationContextAware’s setApplicationContext (only applicable when running in an application context)
-
ServletContextAware’s setServletContext (only applicable when running in a web application context)
-
postProcessBeforeInitialization methods of BeanPostProcessors
-
InitializingBean’s afterPropertiesSet
-
a custom init-method definition
-
postProcessAfterInitialization methods of BeanPostProcessors
-
postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors
-
DisposableBean’s destroy
-
a custom destroy-method definition
实现aware接口,可以让bean感知到bean自身在spring容器中的一些属性,例如:实现BeanNameAware,就可以在bean中通过setBeanName方法获得bean在bean factory中的bean name;实现ApplicationContextAware,就可以在bean中通过setApplicationContext获得当前bean的ApplicationContext
通过复制现有实例创建新实例
优点:向客户隐藏创建新实例的复杂性,提供让客户能够产生位置类型对象的选项,在某些环境下复制对象比创建对象性能更好
缺点:有时,复制对象相当复杂
用途:在一个复杂的类层次中,当系统必须从其中的许多类型创建对象时,可以考虑。
Map<String, String> env = System.getenv();
Properties properties = System.getProperties();
通过allowCircularReferences设置
默认情况下,spring允许循环依赖,但仅限于使用属性注入的方式,构造器注入不行。
todo spring如何判断循环依赖的?
为什么构造器注入不能支持循环依赖?
通过allowBeanDefinitionOverriding设置
默认情况下,spring允许bean覆盖,在配置文件中定义 bean 时使用了相同的 id 或name,如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖。
---这里只看了针对@configuration的实现。其他可能不同
特殊情况,如果同一个configuration class中配置了同名bean,会保留之前存在的。
加载到同名bd时,会判断两个bd的class name是否相同,相同时会直接跳过bd的构建,只保留原有已加载的,不同时,不会跳过,会去构造第二个bd,之后进行注册,此时可以通过allowBeanDefinitionOverriding设置是否允许bd覆盖。
isOverriddenByExistingDefinition判断是否跳过bd构建
关键代码registerBeanDefinition注册时判断是否允许覆盖
ConfigurationClassBeanDefinitionReader.isOverriddenByExistingDefinition
Is the existing bean definition one that was created from a configuration class? → allow the current bean method to override, since both are at second-pass level. However, if the bean method is an overloaded case on the same configuration class, preserve the existing bean definition.
BeanDefinitionRegistry是spring中的bean definition注册中心接口,掌管所有bean definition的注册。 spring中提供SimpleBeanDefinitionRegistry、DefaultListableBeanFactory、GenericApplicationContext三个实现,其中GenericApplicationContext实现方式是包装了DefaultListableBeanFactory,内部直接转发DefaultListableBeanFactory实现的相关注册接口。SimpleBeanDefinitionRegistry、DefaultListableBeanFactory则通过一个ConcurrentHashMap—beanDefinitionMap来实现,实现方式不太一样,DefaultListableBeanFactory复杂很多。
spring中的所有的bean definition的注册都是通过来实现的
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}