Spring源码之@Bean注解解析

文章目录

  • 使用
  • 源码


使用

Spring @Bean是一个方法级别的注解,用于产生一个被Spring IoC容器所管理的Bean。通常情况下,@Bean可以与@Configuration和@Component注解一起使用(@Configuration和@Component是方法级别的注解)。在默认情况下@Bean注解所产生的Bean是单例模式的,此外,@Bean还可以与@Scope,@Lazy,@DependOn和@Primary注解一起使用。

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {

	//name的别名,效果等同于name
	@AliasFor("name")
	String[] value() default {};

	//用于指定Bean的名称
	@AliasFor("value")
	String[] name() default {};

	@Deprecated
	Autowire autowire() default Autowire.NO;

	//布尔类型,用于限定当前的Bean是否可以自动注入到其他Bean中,默认是true
	boolean autowireCandidate() default true;

	//在初始化Bean实例时需要调用的方法名称。默认没有要调用的方法
	//注意initMethod所指定的方法必须是不带入参的方法,且该方法允许在运行时抛出异常
	String initMethod() default "";

	//在关闭应用上下文时要在Bean中调用的方法名称,默认不调用任何方法
	String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;

}

源码

ConfigurationClassParser#doProcessConfigurationClass

// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
	configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

// Process default methods on interfaces
//处理接口中有@Bean注解的,逻辑差不多
processInterfaces(configClass, sourceClass);

检索@Bean修饰的方法,把方法的metadata和类configClass封装成BeanMethod
加入到ConfigurationClass中的beanMethods集合中,这里的作用就是收集@Bean
修饰的方法

要想进行实例化,那必须先转换为BeanDefinition,我们已经把需要处理的@Bean
都收集好了,接下里就是对集合中的进行load操作

this.reader.loadBeanDefinitions(configClasses);
...
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
	loadBeanDefinitionsForBeanMethod(beanMethod);
}

这里循环遍历每个BeanMethod,交给ConfigurationClassBeanDefinitionReader处理

//拿到@Bean修饰的方法的类
ConfigurationClass configClass = beanMethod.getConfigurationClass();
//方法的元数据
MethodMetadata metadata = beanMethod.getMetadata();
//方法名
String methodName = metadata.getMethodName();

//拿到注解信息
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");

// Consider name and any aliases
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

// 注册别名,@Bean注解的name属性的值
for (String alias : names) {
	this.registry.registerAlias(beanName, alias);
}

//实例化一个BeanDefinition
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

//@Bean修饰的是静态方法,设置beanClass和factoryMethod的值
if (metadata.isStatic()) {
	// static @Bean method
	if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
		beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
	}
	else {
		beanDef.setBeanClassName(configClass.getMetadata().getClassName());
	}
	beanDef.setUniqueFactoryMethodName(methodName);
}
//如果@Bean修饰的是非静态方法,设置factoryBean和factoryMethod的值
else {
	// instance @Bean method
	beanDef.setFactoryBeanName(configClass.getBeanName());
	beanDef.setUniqueFactoryMethodName(methodName);
}

//填充BeanDefinition的属性(@Lazy,@Primary,@Dependson,@Role,@Description)
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

//设置initMethod
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
	beanDef.setInitMethodName(initMethodName);
}
//设置destroyMethod
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
...
//Scope等属性相关操作
...
//把BeanDefinition注册到注册器中BeanDefinitionRegistry
this.registry.registerBeanDefinition(beanName, beanDefToRegister);

你可能感兴趣的:(Spring源码,spring,源码,bean)