您现在的位置是:首页 >技术杂谈 >Spring IOC网站首页技术杂谈
Spring IOC
spring是什么
spring是一个企业级开发的轻量级框架由spring衍生出来的springmvc、springboot被称之为Java程序员的“春天”。spring最重要的两个组件就是SpringIOC容器与AOP,IOC即控制反转,依靠DI(依赖注入)实现,简而言之就是原来对象的创建是由我们自己来管理的,而有了IOC容器之后对象的创建就交给了容器来管理,极大降低了程序之间的耦合,程序的灵活度,方便后续维护和二次开发。
什么是Bean
Bean就是IOC所有管理的内容,也是我们new出来的“对象”,作为一个面向对象的语言,在程序中我们不得不创建出大量的对象,这就造成了对象与对象之间严重依赖,一旦某一个对象出现异常,就可能导致程序不能正常运行,也不方面我们添加新的功能。但是在Bean交给容器管理后,一切开始变得十分方便。
没有spring之前:
Student student = new Student();
Teacher teacher = new Teacher();
School school = new School();
之后:
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
Entity entity = (Entity) context.getBean("entity");
//或者我们可以直接通过注解,去获取Bean对象
//@Autowired
//@Resource
IOC详解
IOC的核心工程类有两个BeanFactory
,从名字上也不难看相互,他们也就是生产Bean的工程,负责生产和管理各个Bean实例。在项目中我们更多的是使用他的子类,常见的有AbstractApplicationContext
、ApplicationContext
、DefaultListableBeanFactory
、ClassPathXmlApplicationContext
、AnnotationConfigApplicationContext
等等。
我们先来分析一下xml的解析方式
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
@Nullable
private Resource[] configResources;
public ClassPathXmlApplicationContext() {
}
public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent)
throws BeansException {
this(configLocations, true, parent);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
public ClassPathXmlApplicationContext(String path, Class<?> clazz) throws BeansException {
this(new String[] {path}, clazz);
}
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz) throws BeansException {
this(paths, clazz, null);
}
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
@Override
@Nullable
protected Resource[] getConfigResources() {
return this.configResources;
}
}
这之中最关键的方法就是
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
通过我们在xml中定义的Bean信息来实例化容器,即加载所有bean定义并创建所有singleton,在这之中最重要的方法就是```refresh()``方法。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 记录启动时间,校验xml配置文件,初始化applicationListeners监听器
prepareRefresh();
// 告诉子类刷新内部bean工厂
//这一步主要作用是将配置文件定义解析成beanDefine 注册到beanFactory中,会创建一个DefaultListableBeanFactory
//但是这里的bean并没有初始化出来 只是提取配置信息 定义相关的属性
//将这些信息保存到beanDefineMap中(beanName->beanDefine)对应的map
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备bean工厂以便在此上下文中使用.
prepareBeanFactory(beanFactory);
try {
//允许在上下文子类中对bean工厂进行后处理
postProcessBeanFactory(beanFactory);
// 调用在上下文中注册为bean的工厂处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截bean创建的bean处理器
registerBeanPostProcessors(beanFactory);
// 初始化此上下文的消息源
initMessageSource();
// 初始化此上下文的事件多播
initApplicationEventMulticaster();
// 初始化特定上下文子类中的其他特殊bean
onRefresh();
// 检查监听器bean并进行注册
registerListeners();
// 实例化所有剩余的(非惰性init)singleton
finishBeanFactoryInitialization(beanFactory);
// 发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 关闭旧的beanFactory 创建新的beanFactory 并注册
refreshBeanFactory();
//返回上面创建的beanFactory对象(注意这里是自己改造的)
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
logger.info("Bean factory for " + getDisplayName() + ": " + beanFactory);
return beanFactory;
}
首先我们进入refreshBeanFactory方法 我们找到 AbstractRefreshableApplicationContext 对应的实现类
@Override
protected final void refreshBeanFactory() throws BeansException {
//ApplicationContext 如果已经加载了BeanFactory 则销毁所有的Bean 关闭BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory); //核心
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
if (hasBeanFactory()) { destroyBeans();closeBeanFactory()} 首先我们判断是否存在BeanFactory 如果不为空我们就将其销毁 和关闭
接下来 我们新建一个DefaultListableBeanFactory 的beanFactory 对象 我们进入createBeanFactory()方法
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
这步默认创建DefaultListableBeanFactory 对象 这个时候我们的BeanFactory初步形成 这也将是管理整个bean的核心接口
beanFactory.setSerializationId(getId()); 设置相应的序列化id
customizeBeanFactory(beanFactory); 设置对应的属性 1:设置是否可重复定义bean 2设置 可循环依赖 代码如下
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
//是否允许bean定义的覆盖
// BeanDefinition 的覆盖问题大家也许会碰到,
// 就是在配置文件中定义 bean 时使用了相同的 id 或 name
// ,默认情况下,allowBeanDefinitionOverriding 属性为 null,
// 如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖。
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
//是否允许bean 间的循环依赖
// A 依赖 B,而 B 依赖 A。或 A 依赖 B,B 依赖 C,而 C 依赖 A
// 默认情况下,Spring 允许循环依赖,当然如果你在 A 的构造方法中依赖 B,在 B 的构造方法中依赖 A 是不行的。
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
```
这些属性 我们后面会用到
下面进入最核心的方法loadBeanDefinitions(beanFactory); 这个方法将开始解析配置 转化为对应的BeanDefinition对象
我们点进去(进入)AbstractXmlApplicationContext下的
```java
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// 创建同一个XmlBeanDefinitionReader 见名知意 xml的BeanDefine读取器转换器 也就是将xml文件转化为BeanDefinition
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
// 设置当前环境
beanDefinitionReader.setEnvironment(this.getEnvironment());
//这里的setResourceLoader赋值 我们在refresh方法的时候就已经给this赋值
//且看
// super(parent);
// // 将配置文件路径设置给AbstractRefreshableConfigApplicationContext 的 configLocations的属性
// setConfigLocations(configLocations); //这个方法就将配置路径赋值了
// // 由上面的参数传进refresh为true 下面我们就进入refresh方法 spring初始化全程
// if (refresh) {
// refresh();
// }
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
//下面方法是核心
loadBeanDefinitions(beanDefinitionReader);
}
继续进入loadBeanDefinitions(beanDefinitionReader);方法
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//拿到对应配置文件的地址 对应Resources文件夹下面
String[] configLocations = getConfigLocations();
if (configLocations != null) {
System.out.println(configLocations);
reader.loadBeanDefinitions(configLocations);
}
}
点进reader.loadBeanDefinitions(configLocations);方法
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
继续,就不一一贴出来了.我们一直点到XmlBeanDefinitionReader下面的loadBeanDefinitions方法的具体实现
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
// 用一个 ThreadLocal 来存放所有的配置文件资源
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//生成一个输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//核心 我们点进去
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
进入doLoadBeanDefinitions(inputSource, encodedResource.getResource());
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//这里我们将资源文件转化为Document对象
Document doc = doLoadDocument(inputSource, resource);
//开始注册对应的BeanDefinition 我们继续进去
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
我们直接进入DefaultBeanDefinitionDocumentReader 下面的doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// We cannot use Profiles.of(...) since profile expressions are not supported
// in XML config. See SPR-12458 for details.
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//钩子 没有作任何的实现 不理会
preProcessXml(root);
// 解析xml 将xml元素转化为BeanDefinition
parseBeanDefinitions(root, this.delegate);
//钩子 没有作任何的实现 不理会
postProcessXml(root);
this.delegate = parent;
}
根据上面的解释我们直接进入parseBeanDefinitions(root, this.delegate);
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//默认的命令空间 如beans bean import resource alias name会进此方法
parseDefaultElement(ele, delegate);
}
else {
//其他的元素 如扫包 定时器 都会有对应的handler去处理 可以断点看看
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
因为我们这里只是介绍bean的初始化 那么我们暂时只进parseDefaultElement(ele, delegate); 我们点进去
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
//处理import标签
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
//处理alias标签
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//处理bean标签
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 处理beans标签
doRegisterBeanDefinitions(ele);
}
}
通过标签元素找到对应的process 这里我们只进入processBeanDefinition(ele, delegate);方法体
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// xml节点信息转化为BeanDefinitionHolder对象
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//如果有自定义属性的话 进行相应的解析
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// 这一步就是注册bean啦
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
delegate.parseBeanDefinitionElement(ele)方法将节点元素转化为BeanDefinitionHolder 我们进入该方法
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//<bean id="test" class="com.test.seivice.TestService" ></bean>
//解析像上面这种配置
// 获取xml中id对应的值
String id = ele.getAttribute(ID_ATTRIBUTE);
// 获取xml中name对应的值
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
//核心方法 对bean对应的节点进行属性设置 得到xml中全类名
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
//如果配置中没有定义name只定义了class name我们默认类名的首字母小写作为id(这里很常用)
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isTraceEnabled()) {
logger.trace("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
这个方法完成了bean对应节点元素的解析 转化为BeanDefinitionHolder元素 包括beanDefinition(包含类名 ),beanName,别名。
beanDefinition主要定义了bean创建时候的一些属性 比如是否懒加载,是否单例等等 用于后期创建对象的判断依据 可以去看看这个类 我们在看法中也会定义对应bean的创建所约定的规则。
创建为对应的一个BeanDefinitionHolder 我们回到上上面processBeanDefinition这个方法
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());在这里我们注册我们转化的BeanDefinitionHolder对象 进入该方法
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
//拿到对应的beanName 就是我们前面定义的id的名字
//<bean id="test" 。。。> 就是这里的test
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 进一步注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
//如果有别名 同样注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
我们看看DefaultListableBeanFactory下面的注册方法
@Override
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");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
//判断是否重新创建BeanDefinition 如果不为空而且 不是可重复出现的bean则报错(前面已经提到过)
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
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 + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// 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);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
在这里我们需要关注一下DefaultListableBeanFactory这个类 至关重要!
ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。
ApplicationContext 继承了 HierarchicalBeanFactory,Hierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。
AutowireCapableBeanFactory 这个名字中的 Autowire 大家都非常熟悉,它就是用来自动装配 Bean 用的,但是仔细看上图,ApplicationContext 并没有继承它,不过不用担心,不使用继承,不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory() 就知道了。
ConfigurableListableBeanFactory 也是一个特殊的接口,看图,特殊之处在于它继承了第二层所有的三个接口,而 ApplicationContext 没有。这点之后会用到。
DefaultListableBeanFactory也是BeanFactory重要实现类 主要是用来管理对应的beanDefinition 我们看看这个类的属性
/** Map of bean definition objects, keyed by bean name. */
//注册的类就保存在该map中
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** Map of singleton and non-singleton bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
/** Map of singleton-only bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
/** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
上面是BeanFactory常用管理容器
我们接着上面的注册看 我们将解析出来的beanDefinition用
this.beanDefinitionMap.put(beanName, beanDefinition);装起来 后面我们通过getBean(beanName)就是获得对应beanDefinition 获取类名 通过一系列的手段创建出对象
到此 我们基本已经完成了将xml中配置的(类似)
解析为一个个beanDefinition 放在我们beanDefinitionMap中管理起来 但是我们并未创建对象 创建对象在倒数第二步。