美文网首页
spring-core源码分析

spring-core源码分析

作者: 0d1b415a365b | 来源:发表于2017-04-06 02:44 被阅读0次

    概述


    org.springframework.context.ApplicationContext接口是Spring IoC的容器,负责bean的初始化,配置和装配。ApplicationContext通过读取元数据(configuration metadata)获取该把bean注入到哪个对象。元数据可以是XML, Java注解或Java代码。
      Spring提供了几种ApplicationContext的实现。本地化项目使用的ClassPathXMLApplicationContext或FileSystemXMLApplicationContext. 然而XML是比较传统的配置方式,使用注解或代码配合少量XML作为元数据可以使配置更精简。
       在大多数应用场景,我们不需要自己去创建ApplicationContext的实例。例如在web应用中,只需要在web.xml中增加8行配置就可以了:

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    

    Figure 1. The Spring IoC container

    IoC容器的作用

    Configuration metadata

    元数据的三种配置方式:

    • 完全XML
    • 少量XML(component-scan) + Java注解
    • Java代码(全部使用注解)

    1 spring-core 包结构

    <pre>
    src
    └─org
    └─springframework
    ├─asm
    ├─cglib
    │ └─core
    ├─core
    │ ├─annotation
    │ ├─codec
    │ ├─convert
    │ │ ├─converter
    │ │ └─support
    │ ├─env
    │ ├─io
    │ │ ├─buffer
    │ │ └─support
    │ ├─serializer
    │ │ └─support
    │ ├─style
    │ ├─task
    │ │ └─support
    │ └─type
    │ ├─classreading
    │ └─filter
    ├─lang
    ├─objenesis
    └─util
    ├─backoff
    ├─comparator
    ├─concurrent
    └─xml
    </pre>

    1.1 spring-core各模块功能说明

    1.asm Spring将ASM代码重新打包,提供ASM依赖。
    http://blog.csdn.net/whos2002110/article/details/40817939
    2.cglib cglib生成的动态代理类命名规则(className$$classNameBySpringCGLIB$$hashCode)
    3.core
    4.lang 条件编译注解
    5.objenesis 对象实例化工具,封装后提供缓存功能(单例)
    6.util 各种工具类

    2 spring-core.core

    <pre>
    core
    ├─annotation
    ├─codec
    ├─convert
    │ ├─converter
    │ └─support
    ├─env
    ├─io
    │ ├─buffer
    │ └─support
    ├─serializer
    │ └─support
    ├─style
    ├─task
    │ └─support
    └─type
    ├─classreading
    └─filter
    </pre>
    2.1 annotation


    注解解析器和工具类

    AnnotationUtils.getAnnotationAttributes(Annotation)  
    AnnotationUtils.getValue(Annotation annotation, String attributeName)  
    

    2.2 codec

    各种编码解码工具
    2.3 convert


    转码工具

    2.4 env##

    2.4.1 概述####

    env包是Spring3.1开始提供的新的属性管理API,提供配置读取和环境划分能力,主要接口:PropertySource和Environment

    2.4.2 PropertySource####

    PropertySource.png

    PropertySource:属性源,key-value属性对抽象,比如用于配置数据
    PropertyResolver:属性解析器,用于解析相应key的value

    2.4.2.1主要实现类#####

    MapPropertySource:属性来自于一个Map
    ResourcePropertySource:属性来自于一个properties文件
    ServletContextPropertySource:属性来自ServletContext上下文初始化参数
    CompositePropertySource:提供了组合PropertySource的功能,查找顺序就是注册顺序。

    2.4.3 Environment####

    environment类图.png
    Environment:环境,本身是一个PropertyResolver,但是提供了Profile特性,即可以根据环境得到相应数据(即激活不同的Profile,可以得到不同的属性数据,比如用于多环境场景的配置(正式机、测试机、开发机DataSource配置))
    Profile:剖面,Environment使Spring具有了剖面特性,只有激活的剖面的组件/配置才会注册到Spring容器,类似于maven中profile。这是context包中的一个注解。另外context包中还有一个叫做EnviromentAware的类,ApplicationContext是其子类,因此我们在SpringContext中可以获取所有的配置和Profile信息。
    @Inject Environment environment;
    environment.getProperty( AppConfig.SERVER_HOST ),
    
    if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
        if (logger.isInfoEnabled()) {
            logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                    "] not matching: " + getReaderContext().getResource());
        }
        return;
    }
    

    2.5 io##

    2.5.1 概述####

    在日常程序开发中,处理外部资源是很繁琐的事情,我们可能需要处理URL资源、File资源资源、ClassPath相关资源、服务器相关资源(JBoss AS 5.x上的VFS资源)等等很多资源。因此处理这些资源需要使用不同的接口,这就增加了我们系统的复杂性;而且处理这些资源步骤都是类似的(打开资源、读取资源、关闭资源),因此如果能抽象出一个统一的接口来对这些底层资源进行统一访问,是不是很方便,而且使我们系统更加简洁,都是对不同的底层资源使用同一个接口进行访问。
      spring提供一个Resource接口来统一这些底层资源一致的访问,而且提供了一些便利的接口,从而能提供我们的生产力。

    2.5.2 Resource接口####

    Spring的Resource接口代表底层外部资源,对JDK InputStream的扩展,提供了对底层外部资源的一致性访问接口。

    2.5.3 主要实现类####

    2.5.3.1 ByteArrayResource#####

    ByteArrayResource代表byte[]数组资源,对于“getInputStream”操作将返回一个ByteArrayInputStream。ByteArrayResource可多次读取数组资源,即isOpen ()永远返回false。

    2.5.3.2 InputStreamResource#####

    InputStreamResource代表java.io.InputStream字节流,对于“getInputStream ”操作将直接返回该字节流,因此只能读取一次该字节流,即“isOpen”永远返回true。

    2.5.3.4 FileSystemResource

    FileSystemResource代表java.io.File资源,对于“getInputStream ”操作将返回底层文件的字节流,“isOpen”将永远返回false,从而表示可多次读取底层文件的字节流。

    2.5.3.5 ClassPathResource

    ClassPathResource代表classpath路径的资源,将使用ClassLoader进行加载资源。classpath 资源存在于类路径中的文件系统中或jar包里,且“isOpen”永远返回false,表示可多次读取资源。
    ClassPathResource加载资源替代了Class类和ClassLoader类的“getResource(String name)”和“getResourceAsStream(String name)”两个加载类路径资源方法,提供一致的访问方式。
    ClassPathResource提供了三个构造器:
    public ClassPathResource(String path):使用默认的ClassLoader加载“path”类路径资源;
    public ClassPathResource(String path, ClassLoader classLoader):使用指定的ClassLoader加载“path”类路径资源;
    比如当前类路径是“cn.javass.spring.chapter4.ResourceTest”,而需要加载的资源路径是“cn/javass/spring/chapter4/test1.properties”,则将加载的资源在“cn/javass/spring/chapter4/test1.properties”;
    public ClassPathResource(String path, Class<?> clazz):使用指定的类加载“path”类路径资源,将加载相对于当前类的路径的资源;

    2.5.3.6 UrlResource#####

    UrlResource代表URL资源,用于简化URL资源访问。“isOpen”永远返回false,表示可多次读取资源。
    UrlResource一般支持如下资源访问:
    http:通过标准的http协议访问web资源,如new UrlResource(“http://地址”);
    ftp:通过ftp协议访问资源,如new UrlResource(“ftp://地址”);
    file:通过file协议访问本地文件系统资源,如new UrlResource(“file:d:/test.txt”);

    2.5.3.7 ServletContextResource#####

    ServletContextResource代表web应用资源,用于简化servlet容器的ServletContext接口的getResource操作和getResourceAsStream操作;

    2.5.4 ResourceLoader接口####

    public interface ResourceLoader {  
           Resource getResource(String location);  
           ClassLoader getClassLoader();  
    }  
    

    getResource接口用于根据提供的location参数返回相应的Resource对象;而getClassLoader则返回加载这些Resource的ClassLoader。

    Spring提供了一个适用于所有环境的DefaultResourceLoader实现,可以返回ClassPathResource、UrlResource;还提供一个用于web环境的ServletContextResourceLoader,它继承了DefaultResourceLoader的所有功能,又额外提供了获取ServletContextResource的支持。

    ResourceLoader在进行加载资源时需要使用前缀来指定需要加载:“classpath:path”表示返回ClasspathResource,“http://path”和“file:path”表示返回UrlResource资源,如果不加前缀则需要根据当前上下文来决定,DefaultResourceLoader默认实现可以加载classpath资源。

    2.6 serializer##

    序列化和反序列化

    public interface Serializer<T> {
        void serialize(T object, OutputStream outputStream) throws IOException;
    }
    public interface Deserializer<T> {
        T deserialize(InputStream inputStream) throws IOException;
    }
    

    2.7 style

    格式化输出工具类
    ···
    public interface ValueStyler {
    String style(Object value);
    }
    public interface ToStringStyler {
    void styleStart(StringBuilder buffer, Object obj);
    void styleEnd(StringBuilder buffer, Object obj);
    void styleField(StringBuilder buffer, String fieldName, Object value);
    void styleValue(StringBuilder buffer, Object value);
    void styleFieldSeparator(StringBuilder buffer);
    }
    ···

    2.8 task

    2.8.1 概述####

    Java SE 5.0引入了ThreadPoolExecutor、ScheduledThreadPoolExecutor。Spring 2.x借助ConcurrentTaskExecutor和ThreadPoolTaskExecutor能够通过IoC配置形式自定义它们暴露的各个属性。
    TaskExecutor接口,是对java.util.concurrent.Executor接口的扩展。给其他组件提供线程池的抽象。
    例如ApplicationEventMulticaster组件、JMS的AbstractMessageListenerContainer和对Quartz的整合都使用了TaskExecutor抽象来提供线程池。

    task.png

    2.8.2 配置与使用####

    <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <!-- 核心线程数 -->     
        <property name="corePoolSize" value="5" />
        <!-- 最大线程数 -->  
        <property name="maxPoolSize" value="50" />
        <!-- 队列最大长度 -->
        <property name="queueCapacity" value="1000" />
        <!-- 线程池维护线程所允许的空闲时间,默认为60s -->
        <property name="keepAliveSeconds" value="60" />
    </bean>
    
    @Resource(name = "taskExecutor")
    private TaskExecutor taskExecutor;
    taskExecutor.execute(()-> {
        ...
    });
    

    2.8.3 实现类

    从类图上很明显可以看出分为同步Executor和异步Executor。同步比较简单,就是调用一下的run方法。下面主要分析异步。

    • SimpleAsyncTaskExecutor:每次调用都启动一个新线程。但是,它还是支持对并发总数设限,当超过线程并发总数限制时,阻塞新的调用,直到有位置被释放。
    • ConcurrentTaskExecutor:对Java 5 java.util.concurrent.Executor类的适配,暴露了Executor的配置参数作为bean属性,可以配置自己的Executor,可以设置任务装饰器。
    • **ThreadPoolTaskExecutor **:对java.util.concurrent.ThreadPoolExecutor的包装。
    • ThreadPoolTaskScheduler:对java.util.concurrent.ScheduledExecutorService的封装,并提供了@Scheduled 注解,极大简化了ScheduledExecutorService的操作。
      使用方法:
    // 修改spring context配置文件,增加xmlns和xsi
    // xmlns
    xmlns:task="http://www.springframework.org/schema/task"
    // xsi
    http://www.springframework.org/schema/task  
    http://www.springframework.org/schema/task/spring-task-3.1.xsd  
    //增加task注解扫描
    <task:annotation-driven/>  
    // 方法上加Scheduled 注解,支持fixedDelay、Cron等多种方式
    @Scheduled(cron="0/3 * *  * * ? ")   //每3秒执行一次  
    public void foo(){  
        ...  
    } 
    

    3.Spring-Core.utils#

    <pre>
    util
    ├─backoff
    ├─comparator
    ├─concurrent
    └─xml
    </pre>

    3.1 backoff##

    backoff.png

    Spring封装的退避算法,用于获取重试间隔。两个实现类,FixedBackOff是按照固定时间间隔重试,ExponentialBackOff是间隔以指数方式增长。

    3.2 concurrent##

    Spring中对java.util.concurrent.Future的扩展,支持Future适配,FutureTask添加多个回调函数。

    20141119213430375.jpg

    3.2.1 主要类

    ListenableFuture<T>:增加扩展功能使用addCallback()方法支持增加回调函数
    ListenableFutureTask<T>:FutureTask子类,主要是为了增加回调函数注册和回调函数调用功能。该类重写了done()方法,执行对回调函数队列的调用。

    3.2.2 应用####

    这个工具类应用在Spring4.1的异步新特性中。Spring4.1提供了@Asyc注解,被注解的类或方法将拥有异步处理能力

    • 相关的配置:
      <task:annotation-driven />指定@Async使用的线程池
      <task:executor />配置线程池参数

    3.3 各种工具类##

    ClassUtils:Class类工具,提供操作class类的方法。
    比如:获知类、方法上是否有注解,获取类注解,获取某package下所有class等。提供class缓存
    CollectionUtils:集合工具类,提供集合的转换、查找、判空等方法。
    DigestUtils:对java.serurity.MessageDigest的封装,提供单向加密方法。
    ReflectionUtils:反射工具类,提供各种反射操作,并包装了反射过程中可能出现的异常。
    SystemPropertyUtils:placeholder解析工具类。

    相关文章

      网友评论

          本文标题:spring-core源码分析

          本文链接:https://www.haomeiwen.com/subject/gebkgttx.html