目录
1. BeanDefinition
1.1 AbstractBeanDefinition
1.2 RootBeanDefinition
1.3 ChildBeanDefinition
1.4 GenericBeanDefinition
2. BeanDefinitionReader
2.1 AbstractBeanDefinitionReader
2.2 XmlBeanDefinitionReader
2.3 GroovyBeanDefinitionReader
2.4 PropertiesBeanDefinitionReader
3. BeanDefinitionRegistry
3.1 SimpleBeanDefinitionRegistry
3.2 DefaultListableBeanFactory
3.3 GenericApplicationContext
1. BeanDefinition
BeanDefinition 描述了一个 bean 的相关信息,比如 作用域、是否懒加载、依赖 bean 等。
BeanDefinition 告诉 Spring 如何创建 Bean。
类图
1.1 AbstractBeanDefinition
顶层接口的抽象实现类,完成了大部分基本功能。
1.2 RootBeanDefinition
RootBeanDefinition 表示一个 根 bean definition ,可作为其他 bean definition 的父类。
1.3 ChildBeanDefinition
不可以单独存在,在构造的时候就得传一个父 bean definition。
1.4 GenericBeanDefinition
通用 bean definition,可作为 子 bean definiton,也可作为 父 bean definition。
为什么 bean definition 存在父子关系?
主要用于合并功能:将父 bean definition 中的信息 和 子 bean definition 的信息 合在一起给 子 bean definition。
主要实现原理是:先拷贝父类全部属性,然后将子类的值设置上去。
2. BeanDefinitionReader
BeanDefinition 从哪里来呢,就由 BeanDefinitionReader 来读出来。
以下是该接口定义的方法,主要方法就是 loadBeanDefinition ,用来加载、读取 beanDefinition
public interface BeanDefinitionReader {
/**
* 返回用于注册 beanDefinition 的 BeanDefinitionRegistry
*/
BeanDefinitionRegistry getRegistry();
/**
* 返回资源加载器
*/
ResourceLoader getResourceLoader();
/**
* 返回 bean 类加载器
*/
ClassLoader getBeanClassLoader();
/**
* 返回 bean name 生成器
*/
BeanNameGenerator getBeanNameGenerator();
/**
* 从指定的资源 加载 bean definitions
*/
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;
/**
* 从指定的资源 加载 bean definitions
*/
int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;
/**
* 从指定的资源路径 加载 bean definitions
*/
int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;
/**
* 从指定的资源路径 加载 bean definitions
*/
int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}
类图
2.1 AbstractBeanDefinitionReader
实现通用的基本功能
2.2 XmlBeanDefinitionReader
读取 xml 配置的 bean defintion。
现在查看关键方法 loadBeanDefinitions 的源码。
首先做了些资源的前置准备操作,然后调用到了 doLoadBeanDefinitions 来处理。
/**
* 实际的从指定的 XML file 加载 bean definition
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) {
// 省略部分代码
// 1. 加载文档
Document doc = doLoadDocument(inputSource, resource);
// 2. 注册 bean definition
int count = registerBeanDefinitions(doc, resource);
return count;
}
}
1. doLoadDocument加载文档 doLoadDocument
// 简化代码
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}
2. registerBeanDefinitions 注册 bean definition
上一步得到了 Document 对象,下来开始对 Document 进行读取、解析、注册 bean definition
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
// 简化代码
parseBeanDefinitions(root, this.delegate);
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// 简化代码
delegate.parseCustomElement(root);
}
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
// 简化代码
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
public final BeanDefinition parse(Element element, ParserContext parserContext) {
AbstractBeanDefinition definition = parseInternal(element, parserContext);
if (definition != null && !parserContext.isNested()) {
try {
String id = resolveId(element, definition, parserContext);
if (!StringUtils.hasText(id)) {
String[] aliases = null;
if (shouldParseNameAsAliases()) {
String name = element.getAttribute(NAME_ATTRIBUTE);
if (StringUtils.hasLength(name)) {
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
}
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
// 注册 bean definition
registerBeanDefinition(holder, parserContext.getRegistry());
if (shouldFireEvents()) {
BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
postProcessComponentDefinition(componentDefinition);
parserContext.registerComponent(componentDefinition);
}
}
catch (BeanDefinitionStoreException ex) {
String msg = ex.getMessage();
parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element);
return null;
}
}
return definition;
}
2.3 GroovyBeanDefinitionReader
GroovyBeanDefinitionReader 代表从 groovy 文件读取 bean definition
文件语法示例
import org.hibernate.SessionFactory
import org.apache.commons.dbcp.BasicDataSource
def reader = new GroovyBeanDefinitionReader(myApplicationContext)
reader.beans {
dataSource(BasicDataSource) { // <--- invokeMethod
driverClassName = "org.hsqldb.jdbcDriver"
url = "jdbc:hsqldb:mem:grailsDB"
username = "sa" // <-- setProperty
password = ""
settings = [mynew:"setting"]
}
sessionFactory(SessionFactory) {
dataSource = dataSource // <-- getProperty for retrieving references
}
myService(MyService) {
nestedBean = { AnotherBean bean -> // <-- setProperty with closure for nested bean
dataSource = dataSource
}
}
}
loadBeanDefinitions 方法源码
// 简化代码
public int loadBeanDefinitions(EncodedResource encodedResource) {
Closure<Object> beans = new Closure<>(this) {
@Override
public Object call(Object... args) {
invokeBeanDefiningClosure((Closure<?>) args[0]);
return null;
}
};
Binding binding = new Binding() {
@Override
public void setVariable(String name, Object value) {
if (currentBeanDefinition != null) {
applyPropertyToBeanDefinition(name, value);
}
else {
super.setVariable(name, value);
}
}
};
binding.setVariable("beans", beans);
int countBefore = getRegistry().getBeanDefinitionCount();
// groovy 解析
GroovyShell shell = new GroovyShell(getBeanClassLoader(), binding);
shell.evaluate(encodedResource.getReader(), "beans");
int count = getRegistry().getBeanDefinitionCount() - countBefore;
return count;
}
// grovvy 解析回调
@Override
public Object invokeMethod(String name, Object arg) {
Object[] args = (Object[])arg;
if ("beans".equals(name) && args.length == 1 && args[0] instanceof Closure<?> closure) {
return beans(closure);
}
else if ("ref".equals(name)) {
String refName;
if (args[0] == null) {
throw new IllegalArgumentException("Argument to ref() is not a valid bean or was not found");
}
if (args[0] instanceof RuntimeBeanReference runtimeBeanReference) {
refName = runtimeBeanReference.getBeanName();
}
else {
refName = args[0].toString();
}
boolean parentRef = false;
if (args.length > 1 && args[1] instanceof Boolean bool) {
parentRef = bool;
}
return new RuntimeBeanReference(refName, parentRef);
}
else if (this.namespaces.containsKey(name) && args.length > 0 && args[0] instanceof Closure) {
GroovyDynamicElementReader reader = createDynamicElementReader(name);
reader.invokeMethod("doCall", args);
}
else if (args.length > 0 && args[0] instanceof Closure) {
// abstract bean definition
return invokeBeanDefiningMethod(name, args);
}
else if (args.length > 0 &&
(args[0] instanceof Class || args[0] instanceof RuntimeBeanReference || args[0] instanceof Map)) {
return invokeBeanDefiningMethod(name, args);
}
else if (args.length > 1 && args[args.length -1] instanceof Closure) {
return invokeBeanDefiningMethod(name, args);
}
MetaClass mc = DefaultGroovyMethods.getMetaClass(getRegistry());
if (!mc.respondsTo(getRegistry(), name, args).isEmpty()){
return mc.invokeMethod(getRegistry(), name, args);
}
return this;
}
在 invokeBeanDefiningMethod 最后 注册了 bean definition
private GroovyBeanDefinitionWrapper invokeBeanDefiningMethod(String beanName, Object[] args) {
boolean hasClosureArgument = (args[args.length - 1] instanceof Closure);
if (args[0] instanceof Class<?> beanClass) {
if (hasClosureArgument) {
if (args.length - 1 != 1) {
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(
beanName, beanClass, resolveConstructorArguments(args, 1, args.length - 1));
}
else {
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, beanClass);
}
}
else {
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(
beanName, beanClass, resolveConstructorArguments(args, 1, args.length));
}
}
else if (args[0] instanceof RuntimeBeanReference runtimeBeanReference) {
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName);
this.currentBeanDefinition.getBeanDefinition().setFactoryBeanName(runtimeBeanReference.getBeanName());
}
else if (args[0] instanceof Map<?, ?> namedArgs) {
// named constructor arguments
if (args.length > 1 && args[1] instanceof Class<?> clazz) {
List<Object> constructorArgs =
resolveConstructorArguments(args, 2, hasClosureArgument ? args.length - 1 : args.length);
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, clazz, constructorArgs);
for (Map.Entry<?, ?> entity : namedArgs.entrySet()) {
String propName = (String) entity.getKey();
setProperty(propName, entity.getValue());
}
}
// factory method syntax
else {
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName);
// First arg is the map containing factoryBean : factoryMethod
Map.Entry<?, ?> factoryBeanEntry = namedArgs.entrySet().iterator().next();
// If we have a closure body, that will be the last argument.
// In between are the constructor args
int constructorArgsTest = (hasClosureArgument ? 2 : 1);
// If we have more than this number of args, we have constructor args
if (args.length > constructorArgsTest){
// factory-method requires args
int endOfConstructArgs = (hasClosureArgument ? args.length - 1 : args.length);
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, null,
resolveConstructorArguments(args, 1, endOfConstructArgs));
}
else {
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName);
}
this.currentBeanDefinition.getBeanDefinition().setFactoryBeanName(factoryBeanEntry.getKey().toString());
this.currentBeanDefinition.getBeanDefinition().setFactoryMethodName(factoryBeanEntry.getValue().toString());
}
}
else if (args[0] instanceof Closure) {
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName);
this.currentBeanDefinition.getBeanDefinition().setAbstract(true);
}
else {
List<Object> constructorArgs =
resolveConstructorArguments(args, 0, hasClosureArgument ? args.length - 1 : args.length);
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, null, constructorArgs);
}
if (hasClosureArgument) {
Closure<?> callable = (Closure<?>) args[args.length - 1];
callable.setDelegate(this);
callable.setResolveStrategy(Closure.DELEGATE_FIRST);
callable.call(this.currentBeanDefinition);
}
GroovyBeanDefinitionWrapper beanDefinition = this.currentBeanDefinition;
this.currentBeanDefinition = null;
beanDefinition.getBeanDefinition().setAttribute(GroovyBeanDefinitionWrapper.class.getName(), beanDefinition);
// 注册 bean definition
getRegistry().registerBeanDefinition(beanName, beanDefinition.getBeanDefinition());
return beanDefinition;
}
2.4 PropertiesBeanDefinitionReader
PropertiesBeanDefinitionReader 代表从 properties 文件读取 bean definition
文件语法示例
employee.(class)=MyClass // bean is of class MyClass
employee.(abstract)=true // this bean can't be instantiated directly
employee.group=Insurance // real property
employee.usesDialUp=false // real property (potentially overridden)
salesrep.(parent)=employee // derives from "employee" bean definition
salesrep.(lazy-init)=true // lazily initialize this singleton bean
salesrep.manager(ref)=tony // reference to another bean
salesrep.department=Sales // real property
techie.(parent)=employee // derives from "employee" bean definition
techie.(scope)=prototype // bean is a prototype (not a shared instance)
techie.manager(ref)=jeff // reference to another bean
techie.department=Engineering // real property
techie.usesDialUp=true // real property (overriding parent value)
ceo.$0(ref)=secretary // inject 'secretary' bean as 0th constructor arg
ceo.$1=1000000 // inject value '1000000' at 1st constructor arg
loadBeanDefinitions 源码
这个源码就简单了,直接将文件流加载到 properties 里,然后进行注册 bean definition
// 简化代码
public int loadBeanDefinitions(EncodedResource encodedResource, @Nullable String prefix) {
Properties props = new Properties();
// 获取到文件的 inputStream
try (InputStream is = encodedResource.getResource().getInputStream()) {
if (encodedResource.getEncoding() != null) {
// 将流 加载到 Properties 对象里
getPropertiesPersister().load(props, new InputStreamReader(is, encodedResource.getEncoding()));
}
else {
// 将流 加载到 Properties 对象里
getPropertiesPersister().load(props, is);
}
}
// 注册 bean definition
int count = registerBeanDefinitions(props, prefix, encodedResource.getResource().getDescription());
return count;
}
}
3. BeanDefinitionRegistry
BeanDefinitionReader 读取到 BeanDefinition 后,就使用 BeanDefinitionRegistry 来注册 BeanDefinitionRegistry。
类图
有三个直接实现
3.1 SimpleBeanDefinitionRegistry
简单实现(用于测试用的),看看源码如何实现的 注册 bean definition:
以下能够直观的看出,注册 bean definition、删除 bean definition 的本质就是对 map 的操作。
// 简化代码
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
this.beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
if (this.beanDefinitionMap.remove(beanName) == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
}
3.2 DefaultListableBeanFactory
真正的注册逻辑实现在这个类中
观察代码,发现和上面的 SimpleBeanDefinitionRegistry 本质差不多,都是存入 map。只不过在其基础上,增加了许多前置合法性判断功能。
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 abd) {
try {
abd.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()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
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 {
// 第一次注册该 beanName
if (isAlias(beanName)) {
// 是一个别名
if (!isAllowBeanDefinitionOverriding()) {
// 不允许覆盖定义,直接抛出异常
String aliasedName = canonicalName(beanName);
if (containsBeanDefinition(aliasedName)) { // alias for existing bean definition
throw new BeanDefinitionOverrideException(
beanName, beanDefinition, getBeanDefinition(aliasedName));
}
else { // alias pointing to non-existing bean definition
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition for bean '" + beanName +
"' since there is already an alias for bean '" + aliasedName + "' bound.");
}
}
else {
// 删除别名
removeAlias(beanName);
}
}
if (hasBeanCreationStarted()) {
// 工厂的 bean 创建阶段已经启动
// 存在并发风险,同步放入
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
// 注册 bean
this.beanDefinitionMap.put(beanName, beanDefinition);
// 更新 beanDefinitionNames 列表:加入当前的 bean name
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 删除掉 manualSingletonNames 中的 当前 beanName
removeManualSingletonName(beanName);
}
}
else {
// 工厂的 bean 创建阶段没启动
// 没启动,不存在并发风险,直接放进去
// Still in startup registration phase
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();
}
}
3.3 GenericApplicationContext
查看源码,注册 bean definition 其实是委托给了 DefaultListableBeanFactory。
private final DefaultListableBeanFactory beanFactory;
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
小结
BeanDefinition 描述了一个 bean 的相关信息,比如 作用域、是否懒加载、依赖 bean 等。
BeanDefinition 告诉 Spring 如何创建 Bean。
BeanDefinition 由 BeanDefinitionReader 来读出来 使用 BeanDefinitionRegistry 注册到 BeanFactory
参考
- BeanDefinition详解 - 知乎 (zhihu.com)
- Spring IoC容器中核心定义之------BeanDefinition深入分析