Spring-SimpleAliasRegistry

AliasRegistry

  • SimpleAliasRegistry继承org.springframework.core.AliasRegistry
  1. public interface AliasRegistry {
  2. /**
  3. * Given a name, register an alias for it.
  4. * 别名注册
  5. *
  6. * @param name the canonical name
  7. * @param alias the alias to be registered
  8. * @throws IllegalStateException if the alias is already in use
  9. * and may not be overridden
  10. * @see SimpleAliasRegistry
  11. * @see org.springframework.context.support.GenericApplicationContext
  12. */
  13. void registerAlias(String name, String alias);
  14. /**
  15. * Remove the specified alias from this registry.
  16. * 别名移除
  17. *
  18. * @param alias the alias to remove
  19. * @throws IllegalStateException if no such alias was found
  20. */
  21. void removeAlias(String alias);
  22. /**
  23. * Determine whether this given name is defines as an alias
  24. * (as opposed to the name of an actually registered component).
  25. * 是不是别名
  26. *
  27. * @param name the name to check
  28. * @return whether the given name is an alias
  29. */
  30. boolean isAlias(String name);
  31. /**
  32. * Return the aliases for the given name, if defined.
  33. * 从别名注册map中获取别名信息
  34. *
  35. * @param name the name to check for aliases
  36. * @return the aliases, or an empty array if none
  37. */
  38. String[] getAliases(String name);
  39. }

SimpleAliasRegistry

  1. /**
  2. * Simple implementation of the {@link AliasRegistry} interface.
  3. * Serves as base class for
  4. * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
  5. * implementations.
  6. *
  7. * @author Juergen Hoeller
  8. * @since 2.5.2
  9. */
  10. public class SimpleAliasRegistry implements AliasRegistry {
  11. /**
  12. * Logger available to subclasses.
  13. */
  14. protected final Log logger = LogFactory.getLog(getClass());
  15. /**
  16. * Map from alias to canonical name.
  17. * 存放别名的map(线程安全的),
  18. * 结构: alias-> name
  19. */
  20. private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
  21. /**
  22. * {@code <alias name="appleBean" alias="hhh"/>}
  23. *
  24. * @param name the canonical name
  25. * alias 标签的name属性
  26. * @param alias the alias to be registered
  27. * alias 标签的alias属性
  28. */
  29. @Override
  30. public void registerAlias(String name, String alias) {
  31. Assert.hasText(name, "'name' must not be empty");
  32. Assert.hasText(alias, "'alias' must not be empty");
  33. synchronized (this.aliasMap) {
  34. // 判断: 别名和名字是否相同
  35. if (alias.equals(name)) {
  36. //相同在别名map中移除
  37. this.aliasMap.remove(alias);
  38. if (logger.isDebugEnabled()) {
  39. logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
  40. }
  41. }
  42. else {
  43. // 不相同
  44. // 从map对象中获取别名为alias的value
  45. String registeredName = this.aliasMap.get(alias);
  46. if (registeredName != null) {
  47. // 判断map中是否有有一个别名和传入的name相同的内容
  48. if (registeredName.equals(name)) {
  49. // An existing alias - no need to re-register
  50. return;
  51. }
  52. if (!allowAliasOverriding()) {
  53. throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
  54. name + "': It is already registered for name '" + registeredName + "'.");
  55. }
  56. if (logger.isDebugEnabled()) {
  57. logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
  58. registeredName + "' with new target name '" + name + "'");
  59. }
  60. }
  61. // 别名环检查
  62. checkForAliasCircle(name, alias);
  63. // 放入 map 对象中 alias-> name
  64. this.aliasMap.put(alias, name);
  65. if (logger.isTraceEnabled()) {
  66. logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
  67. }
  68. }
  69. }
  70. }
  71. /**
  72. * Return whether alias overriding is allowed.
  73. * Default is {@code true}.
  74. * 是否允许重写别名
  75. */
  76. protected boolean allowAliasOverriding() {
  77. return true;
  78. }
  79. /**
  80. * Determine whether the given name has the given alias registered.
  81. * <p>
  82. * 递归判断是否已经存在别名
  83. *
  84. * @param name the name to check
  85. * @param alias the alias to look for
  86. * @since 4.2.1
  87. */
  88. public boolean hasAlias(String name, String alias) {
  89. for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
  90. // 获取key值
  91. String registeredName = entry.getValue();
  92. if (registeredName.equals(name)) {
  93. String registeredAlias = entry.getKey();
  94. // 循环引用判断
  95. if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
  96. return true;
  97. }
  98. }
  99. }
  100. return false;
  101. }
  102. /**
  103. * 别名移除
  104. *
  105. * @param alias the alias to remove
  106. */
  107. @Override
  108. public void removeAlias(String alias) {
  109. synchronized (this.aliasMap) {
  110. // 判断是否移除成功
  111. String name = this.aliasMap.remove(alias);
  112. if (name == null) {
  113. throw new IllegalStateException("No alias '" + alias + "' registered");
  114. }
  115. }
  116. }
  117. /**
  118. * 判断是否是一个别名,校验方式{@link org.springframework.core.SimpleAliasRegistry#aliasMap} 的key是否包含
  119. *
  120. * @param name the name to check
  121. * @return
  122. */
  123. @Override
  124. public boolean isAlias(String name) {
  125. return this.aliasMap.containsKey(name);
  126. }
  127. /**
  128. * 获取别名列表
  129. *
  130. * @param name the name to check for aliases
  131. * @return
  132. */
  133. @Override
  134. public String[] getAliases(String name) {
  135. List<String> result = new ArrayList<>();
  136. synchronized (this.aliasMap) {
  137. retrieveAliases(name, result);
  138. }
  139. return StringUtils.toStringArray(result);
  140. }
  141. /**
  142. * Transitively retrieve all aliases for the given name.
  143. * 根据 name 获取别名
  144. *
  145. * @param name the target name to find aliases for
  146. * @param result the resulting aliases list
  147. */
  148. private void retrieveAliases(String name, List<String> result) {
  149. // 循环获取
  150. this.aliasMap.forEach((alias, registeredName) -> {
  151. if (registeredName.equals(name)) {
  152. result.add(alias);
  153. // 递归查询循环引用的别名
  154. retrieveAliases(alias, result);
  155. }
  156. });
  157. }
  158. /**
  159. * Resolve all alias target names and aliases registered in this
  160. * factory, applying the given StringValueResolver to them.
  161. * <p>The value resolver may for example resolve placeholders
  162. * in target bean names and even in alias names.
  163. *
  164. * @param valueResolver the StringValueResolver to apply
  165. */
  166. public void resolveAliases(StringValueResolver valueResolver) {
  167. Assert.notNull(valueResolver, "StringValueResolver must not be null");
  168. synchronized (this.aliasMap) {
  169. Map<String, String> aliasCopy = new HashMap<>(this.aliasMap);
  170. aliasCopy.forEach((alias, registeredName) -> {
  171. String resolvedAlias = valueResolver.resolveStringValue(alias);
  172. String resolvedName = valueResolver.resolveStringValue(registeredName);
  173. if (resolvedAlias == null || resolvedName == null || resolvedAlias.equals(resolvedName)) {
  174. this.aliasMap.remove(alias);
  175. }
  176. else if (!resolvedAlias.equals(alias)) {
  177. String existingName = this.aliasMap.get(resolvedAlias);
  178. if (existingName != null) {
  179. if (existingName.equals(resolvedName)) {
  180. // Pointing to existing alias - just remove placeholder
  181. this.aliasMap.remove(alias);
  182. return;
  183. }
  184. throw new IllegalStateException(
  185. "Cannot register resolved alias '" + resolvedAlias + "' (original: '" + alias +
  186. "') for name '" + resolvedName + "': It is already registered for name '" +
  187. registeredName + "'.");
  188. }
  189. checkForAliasCircle(resolvedName, resolvedAlias);
  190. this.aliasMap.remove(alias);
  191. this.aliasMap.put(resolvedAlias, resolvedName);
  192. }
  193. else if (!registeredName.equals(resolvedName)) {
  194. this.aliasMap.put(alias, resolvedName);
  195. }
  196. });
  197. }
  198. }
  199. /**
  200. * Check whether the given name points back to the given alias as an alias
  201. * in the other direction already, catching a circular reference upfront
  202. * and throwing a corresponding IllegalStateException.
  203. * <p>
  204. * 判断是否循环别名
  205. *
  206. * @param name the candidate name
  207. * @param alias the candidate alias
  208. * @see #registerAlias
  209. * @see #hasAlias
  210. */
  211. protected void checkForAliasCircle(String name, String alias) {
  212. if (hasAlias(alias, name)) {
  213. throw new IllegalStateException("Cannot register alias '" + alias +
  214. "' for name '" + name + "': Circular reference - '" +
  215. name + "' is a direct or indirect alias for '" + alias + "' already");
  216. }
  217. }
  218. /**
  219. * Determine the raw name, resolving aliases to canonical names.
  220. *
  221. * @param name the user-specified name
  222. * @return the transformed name
  223. */
  224. public String canonicalName(String name) {
  225. String canonicalName = name;
  226. // Handle aliasing...
  227. String resolvedName;
  228. do {
  229. resolvedName = this.aliasMap.get(canonicalName);
  230. if (resolvedName != null) {
  231. canonicalName = resolvedName;
  232. }
  233. }
  234. while (resolvedName != null);
  235. return canonicalName;
  236. }
  237. }