Spring源码分析之BeanDefinition
前言
我们定义的所有Bean,不管是通过XML文件定义的,或者通过@Component注解定义的,或者通过@Bean注解定义的,
最后都会转换成一系列的BeanDefinition对象,保存到BeanDefinitionRegistry(注册表)中。
BeanDefinition和Bean实例的关系就类似于Java类和Java对象的关系,Spring通过各种来源如XML或JavaConfig来加载BeanDefinition,
后续通过BeanDefinition来创建Bean实例。BeanDefinition中保存了Bean的所有信息,如名称,所属Class,是否延迟加载等。
BeanDefinition定义
BeanDefinition接口定义如下
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
//默认只提供singleton(单例)和prototype(原型,每次都会创建对象)两种,但也可以扩展
//如基于web的扩展的scope有request, session
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
//用户定义的Bean一般使用这个
int ROLE_APPLICATION = 0;
//暂时不知道哪里使用
int ROLE_SUPPORT = 1;
//Spring内部定义的Bean一般使用这个
int ROLE_INFRASTRUCTURE = 2;
//所属父Bean,可以继承父Bean的配置信息
void setParentName(String parentName);
String getParentName();
//Bean的类名称,后续要通过反射来创建Bean实例
void setBeanClassName(String beanClassName);
String getBeanClassName();
//Bean的scope,一般我们自己定义的Bean默认就是singleton
void setScope(String scope);
String getScope();
//设置是否懒加载,默认非懒加载(会在创建ApplicationContext的过程中提前创建Bean,懒加载的话就是在第一次getBean()时创建Bean)
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
//设置该Bean依赖的所有的Bean(这里的依赖不是指属性依赖@Autowire这种),而是约定一种依赖关系,如A依赖B,那么在创建A前必须先创建B
void setDependsOn(String... dependsOn);
String[] getDependsOn();
//设置该Bean是否可以注入到其他Bean中,只对根据类型注入有效,如果根据名称注入,即使这边设置了false也是可以的,默认为true
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
//是否为主要,同一接口的多个实现,如果没有指定名字,Spring会优先选择设置primary为true的Bean
void setPrimary(boolean primary);
boolean isPrimary();
// 如果该Bean使用工厂方法来创建,需要指定工厂Bean名称。
void setFactoryBeanName(String factoryBeanName);
String getFactoryBeanName();
//指定工厂类中的工厂方法名称
void setFactoryMethodName(String factoryMethodName);
String getFactoryMethodName();
//构造器参数
ConstructorArgumentValues getConstructorArgumentValues();
//Bean中的属性值
MutablePropertyValues getPropertyValues();
//是否为singleton
boolean isSingleton();
//是否为prototype
boolean isPrototype();
//如果这个Bean被设置为abstract,那么不能被实例化,
boolean isAbstract();
}
相关类图如下
Spring提供了不同类型的BeanDefinition实现,
ScannedGenericBeanDefinition: 扫描@Component注解加载的BeanDefinition。
ConfigurationClassBeanDefinition: 扫描@Configuration注解类下包含@Bean注解的方法加载的BeanDefinition。
GenericBeanDefinition: 通用的BeanDefinition实现。
BeanDefinitionRegistry
相关类图如下
DefaultListableBeanFactory就是IOC容器的最终实现类,既实现了BeanFactory接口,也实现了BeanDefinitionRegistry接口,
所以它不仅是Bean容器,也是BeanDefinition注册表,同时管理Bean和BeanDefinition。
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
public class TestBeanDefinition {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class);
definitionBuilder.addPropertyValue("username", "lisi");
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
System.out.println("==========");
beanFactory.registerBeanDefinition("userService", definitionBuilder.getBeanDefinition());
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
UserService userService = (UserService) beanFactory.getBean("userService");
System.out.println(userService.getUsername());//lisi
}
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class UserService {
private String username;
}
}
我们可以自己创建一个BeanDefinition,将它注册到BeanDefinitionRegistry,后续BeanFactory就根据BeanDefinition来创建Bean实例。
DefaultListableBeanFactory内部是通过一个ConcurrentHashMap来存储Bean名称和BeanDefinition的对应关系的。
参考
Spring IOC 容器源码分析
RootBeanDefinition与GenericBeanDefinition (转)