zoukankan      html  css  js  c++  java
  • 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;
        }
    
    }






















  • 相关阅读:
    《你早该这么玩Excel》书摘
    如何提高你的移动开发中AS3/AIR性能
    Starling之资源管理类
    新版Chrome手动安装flashplayer plugin无效的问题
    常用排序算法比较
    pureMVC框架
    AS3.0的事件机制
    如何成为强大的程序员?
    Starling实现的3D云彩效果
    EnterFrame和Timer区别
  • 原文地址:https://www.cnblogs.com/wangpin/p/8325850.html
Copyright © 2011-2022 走看看