浅谈@Configuration注解原理

本文详细介绍了Spring框架中的AnnotationConfigApplicationContext类,该类主要用于处理基于注解的配置。通过不同的构造器,我们可以创建并初始化上下文,然后通过register()方法注册组件类或使用scan()方法扫描特定包来加载bean定义。此外,还讨论了设置环境、Bean名称生成器和作用域解析器的方法。最后,重点讲述了registerBean()方法,用于注册自定义bean。了解这些核心方法对于理解和使用Spring的注解配置至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@Configuration注解实现类为AnnotationConfigApplicationContext
AnnotationConfigApplicationContext

/**
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory.
	 * @param beanFactory the DefaultListableBeanFactory instance to use for this context
	 */
	public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
		super(beanFactory);
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given component classes and automatically refreshing the context.
	 * @param componentClasses one or more component classes — for example,
	 * {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}

	/**
	 * Create a new AnnotationConfigApplicationContext, scanning for components
	 * in the given packages, registering bean definitions for those components,
	 * and automatically refreshing the context.
	 * @param basePackages the packages to scan for component classes
	 */
	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
		scan(basePackages);
		refresh();
	}

有4种构造器

  1. 初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner对象,它需要通过注册调用填充,然后手动刷新。
  2. 先使用给定的DefaultListableBeanFactory创建一个新的AnnotationConfigApplicationContext然后初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner对象
  3. 创建一个新的AnnotationConfigApplicationContext,从给定的组件类派生bean定义,并自动刷新上下文
  4. 创建一个新的AnnotationConfigApplicationContext,扫描给定包中的组件,为这些组件注册bean定义,并自动刷新上下文。

我们看里面最重要的几个方法
1.setEnvironment(将给定的自定义环境传播到底层的AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。)

@Override
	public void setEnvironment(ConfigurableEnvironment environment) {
		super.setEnvironment(environment);
		this.reader.setEnvironment(environment);
		this.scanner.setEnvironment(environment);
	}

2.setBeanNameGenerator(设置Bean名称,任何对这个方法的调用必须发生在调用register(Class…)和/或scan(String…)之前)

public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
		this.reader.setBeanNameGenerator(beanNameGenerator);
		this.scanner.setBeanNameGenerator(beanNameGenerator);
		getBeanFactory().registerSingleton(
				AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
	}

3.setScopeMetadataResolver(设置Bean的作用域,即判断注册的Bean 是原生类型(prototype)还是单例(singleton)类型,任何对这个方法的调用必须发生在调用register(Class…)和/或scan(String…)之前。)

public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
		this.reader.setScopeMetadataResolver(scopeMetadataResolver);
		this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
	}

4.register(注册一个或多个要处理的组件类。 注意,为了让上下文完全处理新类,必须调用refresh())

	@Override
	public void register(Class<?>... componentClasses) {
		Assert.notEmpty(componentClasses, "At least one component class must be specified");
		this.reader.register(componentClasses);
	}

5.scan(在指定的基包中执行扫描。 请注意,为了让上下文完全处理新类,必须调用refresh()。)

@Override
	public void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		this.scanner.scan(basePackages);
	}

6.registerBean从给定的bean类注册一个bean,使用给定的元数据信息获取一个新实例(通常声明为lambda表达式或方法引用),也可以定制它的bean定义元数据(通常声明为lambda表达式)。 这个方法可以被重写,以适应所有registerBean方法的注册机制(因为它们都委托给这个方法)。
参数: beanName—bean的名称(可能为空) bean class—bean的类 Supplier——用于创建bean实例的回调函数(在null的情况下,解析一个公共构造函数来自动连接) customizer——一个或多个用于定制工厂的BeanDefinition的回调函数,例如设置一个lazy-init或主标志

@Override
	public <T> void registerBean(@Nullable String beanName, Class<T> beanClass,
			@Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) {

		this.reader.registerBean(beanClass, beanName, supplier, customizers);
	}

总结
1.通过构造器初始化初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner对象
2.在调用register()之前去,调用setScopeMetadataResolver()设置Bean的作用域并调用setBeanNameGenerator()设置Bean的名称
3.然后调用refresh()方法刷新配置文件(可以是xml配置也可以是其他)
4.最后调用registerBean()注册到容器中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值