spring源码分析计划

准备深入一波spring,mybatis。

---------------------------------------------------------------------------------------------------------------------------------------------

可爱的小清单

Spring典型的分层架构,srp单一职责,1个包只做一件事,

---------------------------------------------------------------------------------------------------------------------------------

很明显核心包是spring-core

spring core的工程下面,分为6个包,分别是asm、cglib、core、lang、objenesis和util。

很明显core是核心

Spring核心

spring三个核心包:bean,core,context

1、spring的设计理念

上面介绍了spring的三个核心组件,如果要在它们中选出核心,那么非bean组件了。spring就是面向bean编程。

Bean在spring中的作用就像Object对OOP的意义一样,

spring解决了一个非常关键的问题,它可以让你把对象之间的依赖关系转而用配置文件管理,也就是他的依赖注入机制,

而这个注入关系在一个叫Ioc的容器中管理,那么在Ioc容器中又是什么?

就是被Bean包裹的对象。spring正是通过把对象包装在Bean中从而达到管理这些对象及做一系列额外操作的目的的。

它这种设计策略完全类似于java实现OOP的设计理念,当然java本身的设计要比Spring复杂太多太多,但是他们都是构建一个数据结构,

然后根据这个数据结构设计他的生存环境,并让它在这个环境中按照一定的规律不停的运动,在它们不停运动中设计一个系列与环境

或者与其他个体完成信息交换。这样想来我们用到其他光剑大概都是类似的设计理念。

2、核心组件如何协同工作

前面说bean是spring中的关键因素,那么Context和Core又有何作用呢?前面把Bean比作一场演出中的演员,Context就是这场演出的舞台背景,而core应该就是演出的道具了。

我们知道bean包装的是Object。而Object必然有数据,如何给这些数据提供生存环境就是Context要解决的问题,对Context来说他就是要发现每个bean之间的关系,为他们建立这种关系

并且维护好这种关系。所以Context就是一个bean关系的集合,这个关系集合又叫Ioc容器,一旦建立起这个Ioc容器,Spring就可以为你工作了。Core组件有什么用武之地呢?

其实Core就是发现、建立和维护每个Bean之间的关系所炫需要的一系列工具,从这个角度来看,把Core组件叫做Util更能让你理解。

3、Bean组件

前面已经说明了Bean组件对spring的重要性,下面看看Bean组件是怎么设计的。bean组件在beans包下。

在这个包下所有类主要解决了3件事:Bean的定义、Bean的创建、对bean的解析。

对Spring的使用者来说唯一需要关心的就是Bean的创建,其他两个由Spring在内部帮你完成,对你来说是透明的。

 

AliasRegistry接口:管理别名的公共接口,用作BeanDefintionRegistry的超级接口。
public interface AliasRegistry {
    /**
     * 给一个名称注册一个别名
     */
    void registerAlias(String name, String alias);

    /**
     * 从注册中撤出一个别名
     */
    void removeAlias(String alias);

    /**
     * 这个name是否有别名
     */
    boolean isAlias(String name);

    /**
    * 如果有别名的化,返回
     */
    String[] getAliases(String name);

}
BeanDefinitionRegistry该接口的作用是向注册表中注册 BeanDefinition 实例,完成注册的过程。
public interface BeanDefinitionRegistry extends AliasRegistry {

    //像注册表中添加一个实例BeanDefinition
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException;

    //根据beanName移除一个BeanDefintion实例
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    //从注册中取得指定的 BeanDefinition 实例
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    //判断 BeanDefinition 实例是否在注册表中(是否注册)
    boolean containsBeanDefinition(String beanName);
 
    //取得注册表中所有 BeanDefinition 实例的 beanName(标识)
    String[] getBeanDefinitionNames();
    
    //返回注册表中 BeanDefinition 实例的数量
    int getBeanDefinitionCount();

    //beanName(标识)是否被占用
    boolean isBeanNameInUse(String beanName);

}
下面看一下实现类SimpleAliasRegistry,
public class SimpleAliasRegistry implements AliasRegistry {

    //从别名映射到name,这里用的并发容器并服了16的初始容量,说明这个类存在并发操作,16估计是直接使用红黑树,还能少一次扩容,可我的代码是5.0.2版本,明天去公司看看低版本的代码初始值是多少,如果是应该不是这个原因。
    private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

    @Override
    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);//别名和name一样没有意义了,还占地方。
        }
        else {
            String registeredName = this.aliasMap.get(alias);
            if (registeredName != null) {
                if (registeredName.equals(name)) {
                    // An existing alias - no need to re-register
                    return;
                }
                if (!allowAliasOverriding()) {
                    throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                            name + "': It is already registered for name '" + registeredName + "'.");
                }
            }
            checkForAliasCircle(name, alias);
            this.aliasMap.put(alias, name);
        }
    }

    /**
     * Return whether alias overriding is allowed.
     * Default is {@code true}.
     */
    protected boolean allowAliasOverriding() {
        return true;
    }

    /**
     * Determine whether the given name has the given alias registered.
     * @param name the name to check
     * @param alias the alias to look for
     * @since 4.2.1
     */
    public boolean hasAlias(String name, String alias) {
        for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
            String registeredName = entry.getValue();
            if (registeredName.equals(name)) {
                String registeredAlias = entry.getKey();
                return (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias));
            }
        }
        return false;
    }

    @Override
    public void removeAlias(String alias) {
        String name = this.aliasMap.remove(alias);
        if (name == null) {
            throw new IllegalStateException("No alias '" + alias + "' registered");
        }
    }

    @Override
    public boolean isAlias(String name) {
        return this.aliasMap.containsKey(name);
    }

    @Override
    public String[] getAliases(String name) {
        List<String> result = new ArrayList<>();
        synchronized (this.aliasMap) {
            retrieveAliases(name, result);
        }
        return StringUtils.toStringArray(result);
    }

    /**
     * Transitively retrieve all aliases for the given name.
     * @param name the target name to find aliases for
     * @param result the resulting aliases list
     */
    private void retrieveAliases(String name, List<String> result) {
        this.aliasMap.forEach((alias, registeredName) -> {
            if (registeredName.equals(name)) {
                result.add(alias);
                retrieveAliases(alias, result);
            }
        });
    }

    /**
     * Resolve all alias target names and aliases registered in this
     * factory, applying the given StringValueResolver to them.
     * <p>The value resolver may for example resolve placeholders
     * in target bean names and even in alias names.
     * @param valueResolver the StringValueResolver to apply
     */
    public void resolveAliases(StringValueResolver valueResolver) {
        Assert.notNull(valueResolver, "StringValueResolver must not be null");
        synchronized (this.aliasMap) {
            Map<String, String> aliasCopy = new HashMap<>(this.aliasMap);
            for (String alias : aliasCopy.keySet()) {
                String registeredName = aliasCopy.get(alias);
                String resolvedAlias = valueResolver.resolveStringValue(alias);
                String resolvedName = valueResolver.resolveStringValue(registeredName);
                if (resolvedAlias == null || resolvedName == null || resolvedAlias.equals(resolvedName)) {
                    this.aliasMap.remove(alias);
                }
                else if (!resolvedAlias.equals(alias)) {
                    String existingName = this.aliasMap.get(resolvedAlias);
                    if (existingName != null) {
                        if (existingName.equals(resolvedName)) {
                            // Pointing to existing alias - just remove placeholder
                            this.aliasMap.remove(alias);
                            break;
                        }
                        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);
                }
            }
        }
    }

    /**
     * Check whether the given name points back to the given alias as an alias
     * in the other direction already, catching a circular reference upfront
     * and throwing a corresponding IllegalStateException.
     * @param name the candidate name
     * @param alias the candidate alias
     * @see #registerAlias
     * @see #hasAlias
     */
    protected void checkForAliasCircle(String name, String alias) {
        if (hasAlias(alias, name)) {
            throw new IllegalStateException("Cannot register alias '" + alias +
                    "' for name '" + name + "': Circular reference - '" +
                    name + "' is a direct or indirect alias for '" + alias + "' already");
        }
    }

    /**
     * Determine the raw name, resolving aliases to canonical names.
     * @param name the user-specified name
     * @return the transformed name
     */
    public String canonicalName(String name) {
        String canonicalName = name;
        // Handle aliasing...
        String resolvedName;
        do {
            resolvedName = this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        }
        while (resolvedName != null);
        return canonicalName;
    }

}






















原文地址:https://www.cnblogs.com/wangpin/p/8325850.html