Spring源码分析系列
Spring源码分析-启动流程浅析 Spring源码分析-Spring源码分析-BeanDefinition
前言
BeanDefinition相当于Bean meta信息,后续创建Bean对象都需要依据BeanDefinition,因此这里需要介绍一下
一、BeanDefinition
BeanDefinition是一个接口,接口定义如下:
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(@Nullable String parentName);
@Nullable String getParentName();
void setBeanClassName(@Nullable String beanClassName);
@Nullable String getBeanClassName();
void setScope(@Nullable String scope);
@Nullable String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(@Nullable String... dependsOn);
@Nullable String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
@Nullable
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
void setInitMethodName(@Nullable String initMethodName);
@Nullable String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable String getDestroyMethodName();
void setRole(int role);
int getRole();
void setDescription(@Nullable String description);
@Nullable String getDescription();
ResolvableType getResolvableType();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
@Nullable String getResourceDescription();
@Nullable BeanDefinition getOriginatingBeanDefinition();
}
BeanDefinition接口中注入比较详细,大家可以参考源码。主要包括如下属性:bean的作用域,bean是否为Primary,bean是否需要FactoryBean,Init/Destroy方法等。
二、AbstractBeanDefinition
spring代码优秀之处,基本上所有的接口,它都会提供一个实现类,而这个实现类往往都是抽象的(Abstract)。我们接下来看一下AbstractBeanDefinition做了哪些工作
2.1、核心字段
@Nullable
private volatile Object beanClass;
@Nullable
private String scope = SCOPE_DEFAULT;
private boolean abstractFlag = false;
@Nullable
private Boolean lazyInit;
private int autowireMode = AUTOWIRE_NO;
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
@Nullable
private String[] dependsOn;
private boolean autowireCandidate = true;
private boolean primary = false;
@Nullable
private String factoryBeanName;
@Nullable
private String factoryMethodName;
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
@Nullable
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides = new MethodOverrides();
@Nullable
private String initMethodName;
@Nullable
private String destroyMethodName;
看到这里不知道大家是否感觉到,这个数据结构很像spring.xml中配置项,不错,这个类(接口)就是spring.xml文件抽像模型。
2.2、核心方法
public void setBeanClass(@Nullable Class<?> beanClass) {
this.beanClass = beanClass;
}
@Override
public void setBeanClassName(@Nullable String beanClassName) {
this.beanClass = beanClassName;
}
public String getBeanClassName() {
Object beanClassObject = this.beanClass;
if (beanClassObject instanceof Class) {
return ((Class<?>) beanClassObject).getName();
}
else {
return (String) beanClassObject;
}
}
public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
String className = getBeanClassName();
if (className == null) {
return null;
}
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
this.beanClass = resolvedClass;
return resolvedClass;
}
2.2、BeanDefinition扫描
AbstractBeanDefinition并没有提供注册的功能,所以注册是在外部实现的,这也体现了一种设计模式:单一职责模式。 在上一篇介绍Spring源码分析-启动流程浅析中有提到会进行包扫描,这个扫描过程其实就是注册BeanDefinition。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
2.3、BeanDefinition注册
在注解场景下,入口类AnnotationConfigApplicationContext继承GenericApplicationContext,在GenericApplicationContext中有一个属性用于保存BeanDefinition
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
...
}
DefaultListableBeanFactory核心字段
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
...
}
通过上面的源码可知,这些map,list就是用于存与BeanDefinition相关的内容,下面是注册BeanDefinition核心方法
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
2.4、动态注册Bean
public class UserService {
private Map<String, User> map = new ConcurrentHashMap<>();
public UserService() {
System.out.println("UserService init....");
}
public User getUser(String name) {
return map.get(name);
}
public void addUser(User user) {
map.put(user.getUsername(), user);
}
}
public class WApp {
public static void main(String[] args) {
GenericApplicationContext context = new AnnotationConfigApplicationContext("com.worker");
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(UserService.class);
context.registerBeanDefinition("userService", beanDefinition);
System.out.println(context.getBean("userService"));
}
}
总结
总体来说,BeanDefinition相关的内容不是很复杂,只要知道BeanDefinition的作用以及包扫描的作用即可。
|