0
点赞
收藏
分享

微信扫一扫

Linux安装MongoDB数据库并内网穿透在外远程访问

科牛 2023-05-23 阅读 71

目录

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深入分析
举报

相关推荐

0 条评论