2018-12-14 小结

2018-12-14 Spring复习小结

Spring 概述

Spring优点:
方便解耦,简化开发
支持AOP编程
声明式事务 (待看)
方便程序的测试 (待看)
集成多种框架
通过封装简化了java EE一些API的使用 JDBC, JavaMail,远程调用等
优秀的源码可通过阅读源码提高水平

核心模块

Core框架按照所属功能可分为五个模块:

IoC: 对象解耦,由IoC容器通过配置负责依赖类之间的创建,拼接,管理,获取等工作。核心接口是BeanFactory,Context模块拓展了国际化,Bean生命周期控制,框架事件体系,资源加载透明化等功能。此外该模块还提供了企业级服务支持,如邮件服务,任务调度,JNDI获取,EJB集成,远程访问等。
AOP 待看
数据访问集成 JDBC, Mybatis(待看),声明式事务(待看)
Web及远程操作 各种web工具, 如通过Listener或Servlet初始化Spring容器,将Spring容器注册到Web容器中。
Web及远程访问 Spring MVC, structs等

Spring 4.0新特性

支持java SE 8 java EE 7
核心容器增强

  1. 添加泛型依赖注入(子类成员变量注入泛型的类型)
  2. Map,List依赖注入,@order
  3. @Lazy
  4. GGLIB代理类增强(待看)

Lambda表达式(需要看个例子
增加Groovy DSL定义Bean
全面支持REST风格web开发
Java 8.0的时间日期API
重复注解支持(@Scheduled @PropertySource)
Optional<>避免非空检查

IoC 容器

DI注入方法

构造函数注入,setter方法注入,静态工厂方法

依赖配置方法

xml, 注释, java配置类

Java反射机制

可以通过java反射类(ClassLoader,Class,Constructor, Method)获取类的构造函数和方法,以间接地方式创建类对象及调用对象的各项方法。Spring对类的管理正是借由java反射机制实现的。

BeanFactory ; ApplicationContext ; WebApplicationContext

BeanFactory的类体系结构:

在这里插入图片描述

ApplicationContext类体系结构

在这里插入图片描述

主要实现类:ClassPathXmlApplicationContext, FIleSystemXmlApplicationContext
其他重要功能接口:
ApplicationEventPublisher, 实现了该事件监听接口的Bean可以接收到容器事件,并对事件进行相应处理。在ApplicationContext的抽象实现类AbstractApplicationContext中存在一个ApplicationEventMulticaster,他负责保存所有的监听器,以便在容器产生context事件时通知这些事件的监听者。
MessageSource为应用提供国际化功能
ResourcePatternResolver 装载Spring配置文件
LifeCycle: 该接口提供了start(), stop()功能,ApplicationContext会将start/stop信息传给容器中所有实现了该接口的Bean,达到管理和控制JMX,任务调度等目的

WebApplicationContext类体系结构

在这里插入图片描述

父子容器

子容器可以访问父容器的bean,父容器不能访问子容器的bean。
子容器可以有一个和父容器id相同的bean
例如: Spring MVC中,展现层bean位于子容器中, 业务层和持久层bean位于父容器中。这样展现层bean可饮用可以引用业务层和持久层的beans,反之不行。

bean生命周期

Factorybean中bean生命周期

在这里插入图片描述

需要注意的点:

  1. 如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor 接口,实例化前会先调用接口的 postProcessBeforeInstantiation()方法。实例化后会调用postProcessAfterInstantiation()(此处可在bean马上要初始化和刚初始化后的时候做一些操作,AOP,动态代理等)
  2. 如果scope=‘prototype’, bean会返回给调用者(调用时初始化bean并交给调用者),调用者负责bean后续生命周期的管理
  3. 如果scope=‘singleton’(默认), bean会放到Spring IoC容器的缓存池中(容器初始化后bean就已经初始化完成),并将bean的引用返回给调用者(调用时返回给调用者该bean的引用),spring继续对这些bean进行后续的生命管理。容器关闭时,如果bean实现了disposableBean()接口则调用该接口的destroy()方法,可以在此写释放资源,记录日志等操作。也可以通过的destroy-method属性指定Bean的销毁方法

可以将Bean生命周期内的方法归为四类

Bean自身的方法:如调用Bean构造函数实例化Bean、调用Setter方法设置属性值、通过的init-method和destory-method所指定的方法

Bean级生命周期的方法:BeanNameAware,BeanFactoryAware, InitializationBean和DisposableBean,这些接口方法直接由Bean实现

容器级生命周期接口方法: 上图中带* 有InstantiationAwareBeanPostProcessor 和BeanPostProcessor这两个接口实现,一般称他们的实现类为后处理器类,处理器接口一般不由Bean本身实现,他们独立于Bean,

实现类以容器附加装置的形式注册到Spring容器中,当Spring创建任何对象时,这些后处理器类都会发生作用,所以这些后处理器类的影响是全局的。容器可以注册多个后处理器,按顺序调用

工厂后处理器接口:包括ApsectJWeavingEnabler, CustomerAutoWireConfigurer, ConfigurationClassPostProcessor 等,也是容器级的,在应用上下文装配配置文件后立即调用。

####ApplicationContext中bean生命周期
ApplicationContext中的Bean生命周期类似于BeanFactory 不同的是如果Bean实现了org.springframework.context.ApplicationContextAware接口,则会增加一个调用该接口方法setApplicationContext()的步骤。
两者的另一个不同之处在于: AC会利用java反射机制自动识别出配置文件中定义的BeanPostProcessor, InstantiationAwareBeanPostProcessor, BeanFactoryPostProcessor, 并自动注册到应用上下文中。而后者需要通过add方法手动注册。在AC中只需要在配置文件中通过bean定义后处理器即可。

在这里插入图片描述

装配Bean

容器成功启动的三个条件

  1. Spring框架的类包已经放在应用程序的类路径下。
  2. 应用程序为Spring提供了完备的Bean配置信息
  3. bean的类都已经放在应用程序的类路径下

Spring在容器初始化时会读取bean的所有配置信息(不同途径),容器内生成一张bean配置注册表,然后根据这张表实例化bean,装配好bean之间的依赖。Bean的配置信息为meta-data,由四部分组成:bean的实现类,属性信息,依赖关系,行为配置(生命周期范围及生命周期内的各过程回掉函数等)。bean的meta-data在容器内对应BeanDefinition形成的bean注册表。目前为止Spring支持基于xml,基于注解,基于java配置类,基于Groovy等动态语言。
在这里插入图片描述

基于scheme格式

基于xml的文件格式采用scheme格式,让不同的配置有了自己的命名空间
在这里插入图片描述

依赖注入的类型和配置
setter方法

利用java反射机制,检查bean对应的类中是否有setter方法,并根据配置把对应的依赖注入进去。setter的命名规范为:setXxx(),而变量的命名,前两个字母要么全部大写,要么全部小写。全部小写会减少错误概率。

构造函数注入

类型匹配,索引匹配,联合两种方法,自身类型反射
构造函数注入有可能造成循环依赖(死锁),遇到这种情况需要改为setter注入

工厂方法注入

工厂方法是常用的设计模式,也是控制反转和单实例设计的主要实现方法。Spring框架中常用工厂方法。工厂类负责创建一个或多个目标类实例,工厂类通常用接口或抽象类变量的形式返回目标类实例。

  1. 非静态工厂类
    非静态工厂类必须先实例化才能通过factory-method制造对象。需要先配置工厂类bean,在通过factory-bean引用工厂类实例
  2. 静态工厂类
    静态工厂类不需实例化就可以通过工厂方法制造对象,只需factory-bean配置工厂类方法即可。
自动注入

@Autowired可以对类成员,类方法进行标注, @Qualifier限制注入bean的名称

注入参数
  1. 字面值
  2. 引用其他bean (bean,local, parent)
  3. 内部bean
  4. null
  5. 级联 (为类内的bean的属性提供注入值)
  6. 集合和集合合并(继承父bean的集合值)
  7. depends-on属性可以使某bean在另一bean实例化前先实例化
  8. 使用idref可让容器在启动时检查引用的正确性
简化配置

p命名空间
自动装配bean

方法注入

如果希望有一个某类中有一个get方法, 每次调用均可以从容其中返回一个新的bean,有一个方法是实现Spring的接口ApplicationContextAware或BeanFactoryAware,如此这般使用ctx.getBean()返回prototype的bean即可。这种配置一般是希望一个singleton Bean获取多个prototype Bean.
其他方法:

lookup方法注入

定义一个接口,声明一个getXxx方法,配置一下该接口,通过lookup-method标签为该方法提供动态实现,再在类中实现该接口,效果和上面的方法等同. 此法需要用到CGLib包

方法替换

用别的bean的方法替换掉这个bean的同名方法。需要配置replaced-method和replacer

bean的继承关系

有多个bean配置大量重复时,可定义抽象bean,再定义子类bean继承抽象bean。

bean的作用域
  1. singleton:容器中仅存一个实例,容器启动时实例化并存放在容器缓存池,也可以设置lazy-init
  2. prototype:每次从容器中调用bean时均返回一个新的实例,调用时实例化
  3. request:每次http请求调用bean时会创建一个新的bean,请求处理完毕后会销毁这个bean
  4. session:同一个http session共享一个bean,不同的http session使用不同的bean。session结束后,实例被销毁
  5. globalSession:一个全局session共享一个bean,一般用于Portlet

使用后三种需要配置web容器,Spring容器需要引入RequestContextListener(它实现了ServletRequestContext接口),该监听器监听HTTP请求事件,因此Spring容器能够掌握Web容器中的请求。另,ContextLoaderListener实现了ServletContextListener接口,负责掌握web容器启动和关闭的事件。

如果需要跨作用域的依赖,比如讲作用域为request的bean注入到singleton的bean中,可以使用aop动态代理技术。在配置文件中添加aop:scoped-proxy后,注入的是request bean的动态代理对象,Spring在其中加入一段逻辑判断当前是在哪个线程里,根据线程找到HTTP request,再在这个request域中找到对应的bean注入进去。

Factory Bean

可以通过定制bean的实例化简化配置过程(不需要一大堆setter,自定义getBean)

基于注解

@Component,@Repository,@Service,@Controller: 把POJO转换为容器管理的bean,配置文件中需要生命context命名空间,并定义扫描类包以应用注解的bean,可以使用resource-pattern来过滤需扫描的类包。
@Lazy @Autowired都不会立刻注入属性值,@Lazy需要在两边同时标注
@Scope表明作用域
@PostConstruct, @PreDestroy 前后处理方法

基于java类

@Configuration 标注为定义类
@Bean 标注定义Bean
可以使用@Configuration类启动容器或向容器中注册(注册定义在其中的bean),只需使用.class,获取bean也可以使用@Bean类的.class属性。也可以在xml中配置被扫描,@Configuration类中也可以引用XML配置信息,这一切都十分灵活。

基于Groovy DSL

Groovy是一种基于JVM的动态语言,结合了python,ruby等动态语言的特性。Groovy相比其他配置方法更加灵活,因为里面可以加入大量的的逻辑。配置示例:
在这里插入图片描述

技术内幕

Spring容器的构成类和内部流程

Spring的AbstractApplicationContext的refresh()方法定义了Spring容器在加载配置文件后的各项处理过程。代码清单如下:
在这里插入图片描述

  1. 根据配置文件实例化BeanFactory, Spring将配置文件信息装入容器的Bean定义注册表(BeanDefinitionRegistry)。此时仅仅获取了BeanFactory的实例,Bean还没有初始化(remind:BeanFactory负责制造bean)
  2. 调用工场后处理器:根据反射机制,从BeanFactoryRegistry中找到所有实现了BeanFactoryPostProcessor接口的Bean,并调用其postProcessBeanFactory()接口方法
  3. 注册Bean后处理器根据反射机制,从BeanFactoryRegistry中找到所有实现了BeanPostProcessor接口的Bean,并将他们注册到容器Bean后处理器的注册表中。
  4. 初始化消息源:初始化容器的国际化消息资源
  5. 初始化ApplicationContextEventMulticaster
  6. 初始化其他特殊的bean
  7. 注册事件监听器
  8. 初始化所有的singleton beans(lazy除外),放入Spring缓存池
  9. 发布上下文刷新事件。事件广播器将事件广播到每个注册的事件监听器中。
BeanDefinition

这个类包括了所有定义bean的metadata,类成员和xml配置文件中的标签可说是一一对应的。BeanDefinition会被注册到BeanDefinitionRegistry中,后续的操作会从 BeanDefinitionRegistry中读取信息。一般情况下BeanDefinition只会在容器启动时被加载或解析,除非容器刷新或重启,这些信息不会发生变化。
创建最终的BeanDefinition有两个步骤

  1. 利用BeanDefinitionReader读取承载配置信息的Resource。这里面可能是半成品,因为配置文件中可能有占位符变量引用外部文件属性
  2. 利用容器中注册的BeanFactoryPostProcessor进行后处理。

####实例化bean
和bean实例化有关的类有:
InstantiationStrategy接口 负责实例化bean,相当于new,并不参与Bean属性设置工作。最常用的实例化策略是SimpleInstantiationStrategy,该策略利用三方法(setter,构造,工厂)创建bean实例CglibSubclassingInstantiationStrategy扩展了该策略,利用Cglib库为Bean动态生成子类,在子类中生成方法注入的逻辑,然后用这个动态生成的子类创建bean的实例。
BeanWrapper 设置属性

容器事件

事件体系中的重要概念:

  1. 事件源:事件的产生者任何一个EventObject都必须有一个事件源
  2. 事件监听器注册表: 注册事件监听器,一旦有事件发布的时候,就会根据注册表的信息通知所有注册过的监听器。在配置文件中配置监听器你,容器启动时会自动注册该监听器。
  3. 事件广播器:负责把事件通知给事件监听器。
Spring的事件类结构

Spring框架定义的事件类型如下:
在这里插入图片描述

有4个容器事件(启动,刷新,停止,关闭)
两个Web应用相关的事件,当一个http请求被处理后,产生该事件。只有在web.xml中定义了DispatcherServlet时才会产生该事件。它拥有两个子类,分别代表Servlet及Portlet的请求事件。

事件监听器接口

Spring的事件监听器接口都继承自ApplicationListener接口,结构如下:
在这里插入图片描述

ApplicationListener接口只定义了一个方法:onApplicationEvent(E event), 该方法接受ApplicationEvent事件对象,在该方法中编写事件的相应处理逻辑。

SmartApplicationListener接口定义了两个方法:

  1. boolean supportsEventType(Class <? entends ApplicationEvent> eventType): 指定监听器支持那种类型的容器事件
  2. boolean supportsSourceType(Class<?> sourceType) 指定监听器仅对何种事件源对象做出相应

GenericApplicationListener接口增强了对泛型事件类型的支持。supportsEventType()方法的参数不再仅局限于ApplicationEvent的子类,而是采用可解析类型ResolvableType。泛型的实际类型信息包括获取类级,字段级别,方法返回值,构造器参数及数组组件类型的泛型信息都可以获得。定义的方法:

  1. boolean supportsEventType(ResolvableType eventType): 指定监听器支持那种类型的容器事件
  2. boolean supportsSourceType(Class<?> sourceType) 指定监听器仅对何种事件源对象做出相应
事件广播器

继承关系如下:
在这里插入图片描述

事件体系的实现

AbstractApplicationContext中完成了事件体系的搭建。AbstractApplicationContext拥有一个applicationEventMulticaster成员变量,提供了容器监听器的注册表。AbstractApplicationContext在refresh()这个容器启动方法中通过以下3个步骤搭建了事件的基础设施

//initialize ApplicationEventMulticaster()
initApplicationEvnetMulticaster();
...
//注册事件监听器(在其他地方可定义多个监听器,此时注册)
registerListeners();
...
//完成刷新并发布容器刷新事件
finishRefresh();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值