bean的基石beanDefinition

什么是Spring框架

Spring是一个轻量级的开发框架,旨在提高开发人员的开发效率以及系统的可维护性。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML配置,基于注解的配置,基于Java的配置。

Spring的7个模块

在这里插入图片描述

  • Spring Core:核心类库,提供IOC服务
  • Spring Context:提供框架式的Bean访问方式,以及企业级功能;
  • Spring AOP:AOP服务
  • Spring DAO:对JDBC的抽象,简化了数据访问异常的处理
  • Spring ORM:对现有的ORM框架的支持
  • Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传
  • Spring MVC:提供面向Web应用的Model-View-Controller实现

Spring中的bean

什么叫bean

在Spring中,那些组成应用程序的主体及由Spring IOC容器所管理的对象,被称之为bean。简单地讲,bean就是由IOC容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。

一个java对象不一定是spring bean,但是spring bean一定是java对象,并且java对象没有生命周期,而spring bean是有生命周期的。

bean的生命周期

常见的有两种:singleton和prototype

1、singleton

容器初始化的时候创建,只会创建一次

2、prototype

获取bean的时候才会被创建,会创建多次

后面会专门对bean的生命周期进行更全面的分析。

建模基石BeanDefinition

beanDefinition扫描进beanDefinitionMap的时机

beanDefinition是怎么被扫描进beanDefinitionMap中的?

首先看下面这段测试代码:

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(App.class);
    }

然后进入AnnotationConfigAppcationContext的构造方法:

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}

在执行这个构造方法之前,会去执行父类GenricApplication的构造方法:

	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

在该构造方法中,创建了一个DefaultListbleBeanFactory,那么就是说子类AnnotationConfigAppcationContext也会拥有父类的这个beanFactory。

回到它的构造方法,此时debug,代码还没执行完register(componentClasses)方法,此时的beanFactory中的beanDefinitionMap中会有如下beanDefinition:

在这里插入图片描述

这5个beanDefinition是spring开天辟地的5个beanDefinition(最新版本只有4个了,有一个已经过期),由spring放进beanDefinitionMap中

当执行完register(componentClasses)方法后:

在这里插入图片描述

可以看到,此时多了一个beanDefinition叫app,它是我们自己定义的加了@ComponentScan注解的bean,通过构造函数传入。

实现了beanFactoryPostProcessor接口的执行时机

接下来我们看实现了beanFactoryPostProcessor接口的类的执行时机。上面执行完register方法后,beanDefinition就被扫描进了beanDefinitonMap中,然后继续执行构造函数中的refresh方法。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				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();
				contextRefresh.end();
			}
		}
	}

这个方法里面有12个核心方法,我们先来看invokeBeanFactoryPostProcessors(beanFactory)这个方法,通过它的名字可以看出是执行BeanFactoryPostProcessors(注意后面加了s,表示复数),当执行完这个方法后:

在这里插入图片描述

此时beanDefinitonMap中多了两个beanDefinition,y是加了@Component注解的类,另外一个是自定义实现了beanFactoryPostProcessors接口的类

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    /**
     * 执行时机:扫描完成之后,也就是类变成BeanDefinition之后,在实例化之前
     * @param beanFactory
     * @throws BeansException
     */
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("-----beanFactoryPostProcessor-----");
    }
}

此时控制台输出:-----beanFactoryPostProcessor-----

**而其实将beanDefinition放入bdmap中的是这个方法中的第一个invokeBeanDefinitionRegistryPostProcessors,它调用的是spring开天辟地5个bean中的ConfigurationClassPostProcessor重写的方法 **,具体会在后面的容器扫描原理中分析。

总结:调用invokeBeanFactoryPostProcessors会执行以下步骤:

1、执行所有需要被执行的BeanFactoryPostProcessor,它会执行spring内置的子类BeanFactoryPostProcessor,完成了扫描ConfigurationClassPostProcessor(这是前面说的开天辟地的5个bd之一)

2、执行程序员提供的BeanFactoryPostProcessor

具体的实现和顺序见后面的扫描原理。

完整代码github

BeanDefinitionSpring中的一个核心概念,它表示了一个Bean的定义。在Spring中,根据BeanDefinition来创建Bean对象。BeanDefinition具有很多属性用来描述Bean的信息和配置。 AnnotatedBeanDefinition是AnnotatedBeanDefinition接口的实现类,表示注解的BeanDefinition。它包含了注解元数据和基本类元数据的信息。AnnotatedBeanDefinition有两个主要的实现类:AnnotatedGenericBeanDefinition和ScannedGenericBeanDefinition。 RootBeanDefinition代表普通的BeanDefinition实现,通过直接实例化BeanDefinition对象来创建。ChildBeanDefinition代表可以设置父BeanDefinition的子BeanDefinition。GenericBeanDefinition代表一般的BeanDefinition,AnnotatedGenericBeanDefinition和ScannedGenericBeanDefinition都是它的两个主要实现类。 综上所述,BeanDefinitionSpring中用来描述Bean的定义的概念,它包含了Bean的各种属性和配置信息。AnnotatedBeanDefinition是注解的BeanDefinition的实现类,它包含了注解元数据和类元数据的信息。RootBeanDefinition和ChildBeanDefinitionBeanDefinition的不同实现方式,GenericBeanDefinition是一般的BeanDefinition,它的两个主要实现类是AnnotatedGenericBeanDefinition和ScannedGenericBeanDefinition。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [BeanDefinition](https://blog.csdn.net/xxssyyyyssxx/article/details/124819785)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值