Spring AnnotationConfigApplicationContext 初始化

博文目录


入口

AnnotationConfigApplicationContext 有多个构造函数, 还有两个成员属性, 分别是 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner, 前者在初始化的时候会注册一些创世纪的处理器, 同时负责将配置类注册成为 BeanDefinition, 后者负责扫描类路径下的 Bean 候选者, 将其注册成为 BeanDefinition

AnnotationConfigApplicationContext()
AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory)
AnnotationConfigApplicationContext(Class<?>... componentClasses)
AnnotationConfigApplicationContext(String... basePackages)

我们常用的构造器是传入配置类的构造器, 实例化后调用 AnnotatedBeanDefinitionReader 的 register 方法将配置类注册成为 BeanDefinition, 然后调用 refresh 方法

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

另一个构造器是传入包路径的构造器, 实例化后调用 ClassPathBeanDefinitionScanner 的 scan 方法将类路径下的Bean候选者注册成为BeanDefinition, 然后调用 refresh 方法

public AnnotationConfigApplicationContext(String... basePackages) {
	this();
	scan(basePackages);
	refresh();
}

AnnotationConfigApplicationContext 还提供了 register 和 scan 等方法用于主动注册和扫描注册 BeanDefinition 的方法, 其实现委托给了内部的 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner

起始

@Configuration
public class Application {

	@Bean
	public String string() {
		return "demo";
	}

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Application.class);
		Object bean = ac.getBean("string");
		System.out.println(bean);
	}

}

new AnnotationConfigApplicationContext(Application.class);

AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	
	// 子类在调用无参构造器时会调用父类的无参构造器, 即隐式调用 super(); 包括抽象类
	// AnnotationConfigApplicationContext - GenericApplicationContext - AbstractApplicationContext - DefaultResourceLoader
	// 调用父类 GenericApplicationContext 的无参构造器, 初始化了 beanFactory 为一个 DefaultListableBeanFactory
	// 调用 AnnotationConfigApplicationContext 的无参构造器, 将 this 传入了 reader 和 scanner 的构造器, 初始化了 reader 和 scanner
	// AnnotationConfigApplicationContext 也是一个 AnnotationConfigRegistry, 委托 DefaultListableBeanFactory 注册 BeanDefinition
	this();
	
	// 把 配置类(可多个) 注册成为 BeanDefinition, 为了在 refresh 中统一解析
	// 加 @Configuration 的配置类被 Spring 称为 Full, 反之称为 Lite, Full 的在解析时会有额外的代理
	register(componentClasses);
	
	// 到这里, 注册了内部使用的类和配置类的 BeanDefinition
	// Spring 中最重要的方法, 是一个模板方法, 该流程定义在 AbstractApplicationContext 中, 贯穿 Spring 应用的整个生命周期, 加载 bean 到销毁 bean
	refresh();
}

配置类是否需要加 @Configuration

有 @Configuration注解, 标记为 FULL 配置类, 没有 @Configuration 注解, 但是存在 @Component, @ComponentScan, @Import, @ImportResource, 或者类中有 @Bean 注解标注的方法, 标记为 LITE 配置类, Full 配置类在解析时会做 CGLib 动态代理

配置类中的 @Bean 配置会受 @Configuration 有无的影响
没有 @Configuration 时, 在创建 Bean b 时, 会调用 b(), 在创建 Bean a 的时候还会再调用一次 b(), B 被实例化两次
配置 @Configuration 时, 调用 b() 会被 CGLib 动态代理加强, 会先从容器中获取, 有的话, 就不会再次调用了, 没有的话, 会创建并加入到容器中

@Bean
public B b() {
	return new B();
}
@Bean
public A a() {
	b();
	return new A();
}

super(); - GenericApplicationContext 的无参构造器

创建了一个 DefaultListableBeanFactory

public GenericApplicationContext() {
	// 创建了一个 DefaultListableBeanFactory, 是 BeanFactory 及其子接口的默认实现
	// 注册 BeanDefinition, 创建和管理 Bean 都是该类完成的, 该类非常重要
	this.beanFactory = new DefaultListableBeanFactory();
}

this(); - AnnotationConfigApplicationContext 的无参构造器

public AnnotationConfigApplicationContext() {
	
	// AnnotatedBeanDefinitionReader 聚合了一个 BeanDefinitionRegistry, 由其代理注册/管理 BeanDefinition 的能力
	// 根据继承实现关系可知, AnnotationConfigApplicationContext 也是一个 BeanDefinitionRegistry, 所以 this 可以直接作为入参传入
	// AnnotatedBeanDefinitionReader 的主要作用是在容器启动早期, 把一些创世纪工具类(角色是基础设施)封装并注册为 BeanDefinition, 同时也提供了主动注册 BeanDefinition 的能力
	// 调用传入的 BeanDefinitionRegistry 的注册 BeanDefinition 的能力, 传入的是一个 AnnotationConfigApplicationContext, 其注册 BeanDefinition 的能力是委托给其 beanFactory 属性的(DefaultListableBeanFactory)
	this.reader = new AnnotatedBeanDefinitionReader(this);
	
	// 提供 applicationContext.scan(basePackage) 主动调用能力
	// 在解析配置类时使用的是该类的另一个实例对象
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

this.reader = new AnnotatedBeanDefinitionReader(this);

AnnotatedBeanDefinitionReader 的主要作用是在容器启动早期, 把一些创世纪工具类(角色是基础架构组件)封装并注册为 BeanDefinition, 主要包括如下工具类, 同时还负责代理 AnnotationConfigApplicationContext 的注册 BeanDefinition 的能力

  • ConfigurationClassPostProcessor 该类非常重要, 用于解析配置类, 把相关类都注册成为 BeanDefinition, 只有该类是 BeanFactoryPostProcessor, 其他的都是 BeanPostProcessor
  • AutowiredAnnotationBeanPostProcessor 解析 @Autowired
  • CommonAnnotationBeanPostProcessor
  • EventListenerMethodProcessor
  • DefaultEventListenerFactory
  • RequiredAnnotationBeanPostProcessor Spring 5.1 已经不再使用该工具类了
  • PersistenceAnnotationBeanPostProcessor

创建 AnnotatedBeanDefinitionReader 对象, 最终会走到 AnnotationConfigUtils

// AnnotationConfigUtils.registerAnnotationConfigProcessors
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
	
	// 这里的 registry 其实是 AnnotationConfigApplicationContext 对象, 从中拿到 beanFactory
	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	
	// ...

	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

	// 将 ConfigurationClassPostProcessor 注册成为 BeanDefinition
	// ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor
	// 拥有修改和注册 BeanDefinition 的能力, 负责解析配置类, 解析加了 @Configuration 的配置类, 解析 @ComponentScan, @ComponentScan 扫描的包, @Import 等, 将这些地方的相关 BeanDefinition 都注册到容器中
	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// 将 AutowiredAnnotationBeanPostProcessor 注册成为 BeanDefinition
	// AutowiredAnnotationBeanPostProcessor 实现了 SmartInstantiationAwareBeanPostProcessor 和 InstantiationAwareBeanPostProcessor 和 MergedBeanDefinitionPostProcessor 和 BeanPostProcessor
	// 解析 @Autowired, 在 Bean 的属性注入的时候会用到
	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));
	}

	// 5.1 开始不注册 RequiredAnnotationBeanPostProcessor
	// 解析 @Required, 是一个 BeanPostProcessor, 在 Bean 的属性注入的时候会用到

	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
	// 将 CommonAnnotationBeanPostProcessor 注册成为 BeanDefinition
	// CommonAnnotationBeanPostProcessor 实现了 DestructionAwareBeanPostProcessor 和 MergedBeanDefinitionPostProcessor 和 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor
	// 注意 CommonAnnotationBeanPostProcessor 继承自 InitDestroyAnnotationBeanPostProcessor
	// 处理 @PostConstruct, @PreDestroy, @Resource, @WebServiceRef, @EJB 等注解
	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));
	}

	// ...

	// 将 EventListenerMethodProcessor 注册成为 BeanDefinition
	// EventListenerMethodProcessor 实现了 BeanFactoryPostProcessor
	// 可以从 BeanFactory 中拿到所有 EventListenerFactory 类型的 Bean, 排序后缓存起来备用
	// 解析 @EventListener, spring 实现事件监听的方式有很多种, 其中一种就是在方法上添加 @EventListener 注解
	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));
	}

	// 将 DefaultEventListenerFactory 注册成为 BeanDefinition
	// 解析 @EventListener
	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;
}
AnnotationConfigUtils.registerPostProcessor(registry, beanDefinition, beanName)
	private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

		// ROLE_INFRASTRUCTURE, 表明当前 BeanDefinition 是基础架构组件, 是 Spring 内部使用的, 和用户无关的
		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		
		// 调用 registry(即 AnnotationConfigApplicationContext) 注册 BeanDefinition
		// 其实是 AnnotationConfigApplicationContext 代理了 DefaultListableBeanFactory 的所有 BeanDefinitionRegistry 能力
		registry.registerBeanDefinition(beanName, definition);
		
		return new BeanDefinitionHolder(definition, beanName);
	}
DefaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinition)

注册 BeanDefinition 其实是使用 AnnotationConfigApplicationContext 的父类 GenericApplicationContext 聚合的 DefaultListableBeanFactory 来实现的, 其内部维护了 BeanDefinitionMap 和 BeanDefinitionNames 两个容器, 用于存放 BeanDefinition 的信息, 注册就是把 BeanDefinition 添加到这两个容器中

// 在 启动注册 BeanDefinition 阶段
// 把 beanName 作为 key, BeanDefinition 作为 value, put 到 beanDefinitionMap 中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 把 beanName add 到 beanDefinitionNames 中
this.beanDefinitionNames.add(beanName);

this.scanner = new ClassPathBeanDefinitionScanner(this);

实例化一个BeanDefinitionScanner, 只用于手动调用 applicationContext.scan(basePackage)

Spring Ioc 加载过程会用到该类的另一个实例来扫描

虽然类路径扫描非常快, 但通过在编译时创建候选的静态列表, 可以提高大型应用程序的启动性能. 在此模式下, 应用程序的所有模块都必须使用此机制, 当 ApplicationContext 检测到此类索引时, 它将自动使用它, 而不是扫描类路径. 启用方式就是 pom 中引入 spring-context-indexer 依赖, 这个过程将产生一个名为 META-INF/spring.components 的文件, 并将包含在jar包中. 如果在类路径中找到 META-INF/spring.components 时, 将自动启用索引. 也可以通过设置 spring.index.ignore 来配置是否启用索引

还有个非常重要的地方, new 的时候会调用 registerDefaultFilters(); 在里面注册扫描时过滤候选 component 的 includeFilters

ClassPathScanningCandidateComponentProvider.registerDefaultFilters();

默认会扫描的 Bean 候选, 包含有 @Component, @ManagedBean, @Named, 像 @Repository, @Service, @Controller 这类持有 @Component 元注解的注解也会被扫描到

protected void registerDefaultFilters() {
	this.includeFilters.add(new AnnotationTypeFilter(Component.class));
	ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
	try {
		this.includeFilters.add(new AnnotationTypeFilter(
				((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
		logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
	}
	catch (ClassNotFoundException ex) {
		// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
	}
	try {
		this.includeFilters.add(new AnnotationTypeFilter(
				((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
		logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
	}
	catch (ClassNotFoundException ex) {
		// JSR-330 API not available - simply skip.
	}
}
ClassPathBeanDefinitionScanner.scan(String… basePackages)

扫描指定包的时候, 会从该包及所有子包中找到 满足包含在 includeFilters 且不包含在 excludeFilters 中的组件, 然后完善属性, 最终注册到 BeanDefinition 容器中

public int scan(String... basePackages) {
	int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

	// 注册扫描到的 BeanDefinition
	doScan(basePackages);

	// Register annotation config processors, if necessary.
	// Register annotation config processors, if necessary.
	// 默认会像 AnnotatedBeanDefinitionReader 一样, 把创世纪类都注册成为 BeanDefinition
	if (this.includeAnnotationConfig) {
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

	return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

register(componentClasses); - AnnotationConfigApplicationContext 注册配置类的 BeanDefinition

委托给 reader把 配置类(可多个) 注册成为 BeanDefinition, 为了在 refresh 中统一解析

加 @Configuration 的配置类被 Spring 称为 Full, 反之称为 Lite, Full 的在解析时会有额外的代理

refresh(); - AbstractApplicationContext 的 refresh 方法

到这里, 注册了内部使用的类和配置类的 BeanDefinition

Spring 中最重要的方法, 是一个模板方法, 该流程定义在 AbstractApplicationContext 中, 贯穿 Spring 应用的整个生命周期, 从加载 bean 到销毁 bean

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// 准备刷新上下文环境
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		// 获取 BeanFactory, 不同子类不同实现
		// 这里拿到的是 GenericApplicationContext 的 beanFactory 属性, 即 DefaultListableBeanFactory, 实现了 BeanDefinitionRegistry
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// 对 BeanFactory 进行属性填充
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			// 预留, 由子类实现
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			// BeanFactoryPostProcessors 和 BeanDefinitionRegistryPostProcessor 主要的功能就是 注册和修改 BeanDefinition
			// 这里将自动或手动注册的各种 BeanFactoryPostProcessors (包括 BeanDefinitionRegistryPostProcessor) 按一定的顺序规则逐个调用其 postProcessBeanDefinitionRegistry 和 postProcessBeanFactory 方法
			// 当前阶段满足条件的只有解析配置类的工具类 ConfigurationClassPostProcessor, 所以 invokeBeanFactoryPostProcessors 方法可以认为就是在解析配置类
			// 会从当前已注册的 BeanDefinition 中找到配置类, 把配置类本身, 配置类上面的 @PropertySource, @ComponentScan, @Component, @Import, @ImportResource 等注解都解析出来, 生成对应的 BeanDefinition 并注册到容器中
			// 在这里会优先调用 getBean 来实例化实现了 BeanFactoryPostProcessor 的组件
			// 如何判断一个 BeanDefinition 是一个配置类?
			// - 有 @Configuration注解的 BeanDefinition, 标记为 FULL 配置类
			// - 没有 @Configuration 注解, 但是有任一 @Component, @ComponentScan, @Import, @ImportResource 注解, 或者类中有 @Bean 注解标注的方法的 BeanDefinition, 标记为 LITE 配置类
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			// 注册 BeanPostProcessor
			// 像处理 @Autowired 的 AutowiredAnnotationBeanPostProcessor 等, 必须在 Bean 实例化前准备好, 到时候才能正常工作
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			// 初始化国际化资源处理器
			initMessageSource();

			// Initialize event multicaster for this context.
			// 创建事件多播器
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// 预留, 由子类实现. 一个空的回调, SpringBoot 就是在这里启动内置的 Web Servlet 容器
			onRefresh();

			// Check for listener beans and register them.
			// 把事件监听器注册到事件多播器上
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			// 主要是实例化并注入属性并初始化所有剩余的满足条件的单例 Bean
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			// 容器完成刷新, 发布刷新事件, SpringCloud 也是从这里启动的
			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();
		}
	}
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以在 Spring 配置文件中使用 `default-lazy-init` 属性来设置全局的延迟初始化。例如: ``` <beans default-lazy-init="true"> <!-- 其他 bean 定义 --> </beans> ``` 这将会导致所有的 bean 都采用延迟初始化的方式,除非在单独的 bean 定义中显式地设置 `lazy-init` 属性为 `false`。 另外,也可以通过在类路径中添加 `META-INF/spring.factories` 文件,并在该文件中添加如下内容来设置全局的延迟初始化: ``` org.springframework.context.annotation.ConfigurationClassPostProcessor.registerLazyInitialization=true ``` 最后,还可以使用 Spring 的 `AbstractApplicationContext` 类的 `setDefaultLazyInitialization` 方法来设置全局的延迟初始化,例如: ``` AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.setDefaultLazyInitialization(true); context.register(AppConfig.class); context.refresh(); ``` ### 回答2: 在Spring中,可以通过配置来设置全局的延迟初始化。要实现这个目标,可以按照以下步骤进行操作。 首先,在Spring的配置文件中,可以通过`<beans>`标签来设置全局的延迟初始化策略。可以使用`default-lazy-init`属性来指定全局的延迟初始化行为。将其设置为`true`,表示所有的bean都将被延迟初始化;将其设置为`false`,表示所有的bean都将立即初始化。例如: ```xml <beans default-lazy-init="true"> <!-- bean definitions here --> </beans> ``` 其次,如果需要对特定的bean进行自定义的延迟初始化设置,可以在相应的bean定义中使用`lazy-init`属性进行配置。将其设置为`true`,表示该bean将被延迟初始化;将其设置为`false`,表示该bean将立即初始化。例如: ```xml <bean id="myBean" class="com.example.MyBean" lazy-init="true"> <!-- bean properties and configuration here --> </bean> ``` 通过上述两种方式,可以实现全局的延迟初始化设置。这样可以有效地控制bean的初始化时机,避免在应用启动过程中加载过多的bean,从而提高应用的性能和响应速度。 ### 回答3: 在Spring中,我们可以使用lazy-init属性来设置全局的延迟初始化。 延迟初始化意味着在第一次访问bean时才会创建实例。相反,如果不设置延迟初始化Spring容器在启动时就会创建所有的bean实例。 要设置全局的延迟初始化,我们可以在Spring配置文件(通常是applicationContext.xml)中使用default-lazy-init属性。例如: <beans default-lazy-init="true"> <!-- bean definitions --> </beans> 在上面的示例中,默认的延迟初始化值设置为true,这意味着所有的bean都会被延迟初始化。如果想要某个特定的bean在启动时立即初始化,可以在其bean定义中明确设置lazy-init属性为false。 延迟初始化对于应用中一些不常用或资源消耗较大的bean很有用,可以提高应用的启动性能。但需要注意的是,如果一个bean在容器启动后需要立即使用,而它被延迟初始化了,那么可能会导致一些问题。因此,在选择是否延迟初始化时,需要仔细考虑应用的需求和性能权衡。 总结来说,要设置全局的延迟初始化,在Spring配置文件中使用default-lazy-init属性,并将其设为true。如果需要某个特定的bean立即初始化,可以在其bean定义中将lazy-init属性设为false。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值