上一篇介绍了BeanFactory体系的所有接口——Spring源码分析——BeanFactory体系之接口详细分析,本篇就接着介绍BeanFactory体系的抽象类和接口。

一、BeanFactory的基本类体系结构(类为主):

Spring源码分析——BeanFactory体系之抽象类、类分析(一)

  上图可与 的图结合分析,一个以接口为主,一个以类为主(PS:Spring的体系结构要分析清楚,不得不曲线救国啊!不然27寸屏幕给我画估计都装不下。)。

具体:

  1、7层的类体系继承。

  2、AbstractBeanFactory实现了最重要的ConfigurableBeanFactory接口,DefaultSingletonBeanRegistry实现了SingletonBeanRegistry单例类注册接口,SimpleAliasRegistry实现了AliasRegistry别名注册接口。

  3、祖先类SimpleAliasRegistry、DefaultSingletonBeanRegistry和子孙类XmlBeanFactory、DefaultListableBeanFactory是完整的类,而中间的类FactoryBeanRegistrySupport、AbstractBeanFactory、AbstractAutowireCapableBeanFactory都是抽象类。

总结:

  具体上来说,XmlBeanFactory光是父类就有6个了,加上自身,总共7层了。实际上分析接口结构就会看到,作为IOC类工厂而言,XmlBeanFactory的类体系结构实际是从祖先AbstractBeanFactory这个类开始的,因为是它实现了BeanFactory的子接口ConfigurableBeanFactory,虽然它继承自FactoryBeanRegistrySupport,但可以说这只是工厂功能的扩充,扩展了对工厂Bean以及工厂所产生的Bean的操作。

 

二、简单的别名注册器——SimpleAliasRegistry

  上篇已经讲过AliasRegistry,非常简单的4个方法,体现了对别名注册的支持,而SimpleAliasRegistry就是它的简单实现。

源码:

public class SimpleAliasRegistry implements AliasRegistry {

    /*
     *用一个支持高并发的ConcurrentHashMap来放置所有的别名
     */
    private final Map<String, String> aliasMap = new ConcurrentHashMap<String, String>(
            16);

    // AliasRegistry的接口方法,注册别名。不允许重复注册。
    public void registerAlias(String name, String alias) {
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        if (alias.equals(name)) {
            this.aliasMap.remove(alias);
        } else {
            if (!allowAliasOverriding()) {
                String registeredName = this.aliasMap.get(alias);
                if (registeredName != null && !registeredName.equals(name)) {
                    throw new IllegalStateException("Cannot register alias '"
                            + alias + "' for name '" + name
                            + "': It is already registered for name '"
                            + registeredName + "'.");
                }
            }
            checkForAliasCircle(name, alias);//alias不能等于name在map中最后的对应(详见checkForAliasCircle方法)
            this.aliasMap.put(alias, name);//alias是key,name是value
        }
    }

    /**
     * 返回是否允许Alias重写,默认为允许
     */
    protected boolean allowAliasOverriding() {
        return true;
    }

    // AliasRegistry的接口方法,移除别名,如果别名未注册,则抛出异常
    public void removeAlias(String alias) {
        String name = this.aliasMap.remove(alias);
        if (name == null) {
            throw new IllegalStateException("No alias '" + alias
                    + "' registered");
        }
    }

    // AliasRegistry的接口方法,给定名称判断是否为别名
    public boolean isAlias(String name) {
        return this.aliasMap.containsKey(name);
    }

    // AliasRegistry的接口方法
    public String[] getAliases(String name) {
        List<String> result = new ArrayList<String>();
        synchronized (this.aliasMap) {
            retrieveAliases(name, result);
        }
        return StringUtils.toStringArray(result);
    }

    /*
     * 找出名字说对应的所有别名。
     */
    private void retrieveAliases(String name, List<String> result) {
        for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {//遍历aliasMap
            String registeredName = entry.getValue();//取aliasMap的每个value
            if (registeredName.equals(name)) {//如果value等于指定的这个name
                String alias = entry.getKey();//取value对应的key
                result.add(alias);//将alias加入
                retrieveAliases(alias, result);//继续查看以alias为value的key
            }
        }
    }

    /*
     * 处理所有的别名,如果处理正确,把原来的用解析后的替换
     */
    public void resolveAliases(StringValueResolver valueResolver) {
        Assert.notNull(valueResolver, "StringValueResolver must not be null");
        synchronized (this.aliasMap) {
            Map<String, String> aliasCopy = new HashMap<String, String>(
                    this.aliasMap);
            for (String alias : aliasCopy.keySet()) {
                String registeredName = aliasCopy.get(alias);//取出key对应的value
                String resolvedAlias = valueResolver.resolveStringValue(alias);//解析后的key
                String resolvedName = valueResolver
                        .resolveStringValue(registeredName);//解析后的value
                if (resolvedAlias.equals(resolvedName)) {//若解析后的key、name相等,就把它们从aliasMap中移除
                    this.aliasMap.remove(alias);
                } else if (!resolvedAlias.equals(alias)) {//若解析后的key不等于原来的Key
                    String existingName = this.aliasMap.get(resolvedAlias);//取出解析后的key对应的value
                    if (existingName != null//如果不为空且不等于解析后的value,就抛出异常
                            && !existingName.equals(resolvedName)) {
                        throw new IllegalStateException(
                                "Cannot register resolved alias '"
                                        + resolvedAlias
                                        + "' (original: '"
                                        + alias
                                        + "') for name '"
                                        + resolvedName
                                        + "': It is already registered for name '"
                                        + registeredName + "'.");
                    }
                    checkForAliasCircle(resolvedName, resolvedAlias);
                    this.aliasMap.remove(alias);
                    this.aliasMap.put(resolvedAlias, resolvedName);
                } else if (!registeredName.equals(resolvedName)) {
                    this.aliasMap.put(alias, resolvedName);
                }
            }
        }
    }

    /*
     * 根据name这个Key,在aliasMap中不断循环的取对应的value,如果取得到,就继续根据这个value取值,不断循环继续。
     * 直到取不到,就把这个在aliasMap中无对应值的key返回。
     */
    public String canonicalName(String name) {
        String canonicalName = name;    //规范名
        // Handle aliasing...
        String resolvedName;//已解析名
        do {
            resolvedName = this.aliasMap.get(canonicalName);//aliasMap中规范名对应的值赋值给已解析名
            if (resolvedName != null) {//如果已解析名存在(即规范名在aliasMap中有对应的值)
                canonicalName = resolvedName;   // 这个已解析名赋值给标准名
            }
        } while (resolvedName != null);//不断循环,直到已解析名不存在
        return canonicalName;
    }

    /*
     * 如果别名alias等于canonicalName(name)就抛出异常
     */
    protected void checkForAliasCircle(String name, String alias) {
        if (alias.equals(canonicalName(name))) {
            throw new IllegalStateException("Cannot register alias '" + alias
                    + "' for name '" + name + "': Circular reference - '"
                    + name + "' is a direct or indirect alias for '" + alias
                    + "' already");
        }
    }

}
View Code

相关文章: