深入理解Spring

Spring两大核心:IoC、AOP
IoC(Inversion of Control):控制反转,别名依赖注入
IoC Service Provider会把相应的被依赖对象注入到被注入对象中,达到 IoC Service Provider为被注入对象服务的目的,控制也从被注入对象转移至 IoC Service Provider
三种依赖注入的方式:构造方法注入、setter方法注入、接口注入
构造方法注入:被注入对象可以通过在其构造方法中声明依赖对象的参数列表,让IoC容器知道需要哪些依赖对象, IoC Service Provider会检查被注入对象的构造方法,取得它所需要的依赖对象列表,进而为其注入相应的对象。同一个对象无法构造两次,所以,被注入对象的构造乃至整个生命周期应该由 IoC Service Provider管理
构造方法注入方式比较直观,对象被构造完成后,即可进入就绪状态,可马上使用
setter方法注入:对于JavaBean对象,可通过setxxx()和getxxx()方法来访问对应属性。setxxx()方法统称为setter方法,同时,getxxx()方法统称为getter方法
setter方法可以更改相应的对象属性,getter方法可以获取相应属性的状态。当前对象为其依赖对象所对应的属性添加setter方法,可以将相应的依赖对象设置到被注入对象中
接口注入:IoC对注入对象注入依赖对象,必须实现某个接口,提供一个方法用来注入依赖对象, IoC Service Provider通过接口了解应该为被注入对象注入什么依赖
FXNewProvider让 IoC Service Provider为其注入所依赖的IFXNewsListener,首先需要实现IFXNewsListenerCallable接口,接口会声明一个叫injectNewsListener方法(方法名随意),方法参数就是依赖对象类型
掌管大局的 IoC Service Provider
IoC Service Provider是一个抽象概念,可以指代任何将IoC场景中的业务对象绑定到一起的实现方式,可以是一段代码,一组相关的类,甚至可以是比较通用的IoC框架或IoC容器
IoC Service Provider的职责
业务对象的构建管理:在IoC场景中,业务对象无需关心所依赖的对象如何构建,如何获取,但这部分工作需要有人来做。 IoC Service Provider将对象的构造逻辑从客户端那里剥离,以免这部分逻辑污染业务对象的实现
业务对象间的依赖绑定: IoC Service Provider通过组合之前构建和管理的所有业务对象,以及各个业务对象间可以识别的依赖关系,将这些对象所依赖的对象注入绑定,保证每个业务对象在使用的时候,可以处于就绪状态
IoC Service Provider使用的注册对象管理信息的方法:
直接编码方法:当前大部分IoC容器都支持直接编码方法,在容器启动之前,可以通过程序编码的方式将被注入对象和依赖对象注册到容器中,并明确它们之间的依赖注入关系
配置文件方式:最常见的是通过XML文件来管理对象注册和对象间的依赖关系,比如Spring IoC容器和在PicoContainer基础上扩展的NanoContainer,都是采用XML文件来管理和保存依赖注入信息的
元数据方式:可以直接在类中使用元数据信息来标注各个对象之间的依赖关系,然后由Guicc框架根据这些注解所提供的信息将这些对象封装后,交给客户端对象使用

 

pring的IoC容器之BeanFactory
Spring提供两种容器类型:BeanFactory、ApplicationContext
BeanFactory:基础类型IoC容器,提供完整的IoC服务支持 ,默认采用延迟初始化,只有当客户端对象需要访问容器中的某个受管对象的时候,才对该受管对象进行初始化以及依赖注入操作
适用场景:资源有限,并且功能要求不是很严格
ApplicationContext:在BeanFactory上所构建,相对比较高级的容器实现,提供一些高级特性,比如事件发布,国际化信息支持等,ApplicationContext所管理的对象,在该类型容器启动之后,默认全部初始化并绑定完成,相较于BeanFactory,ApplicationContext要求更多的系统资源
适用场景:系统资源充足,要求更多功能
BeanFactory可以完成作为 IoC Service Provider的所有职责,包括业务对象的注册,和对象间依赖关系的绑定
DefaultListableBeanFactory既实现了BeanFactory接口,也实现了BeanDefinitionRegistry接口,该接口定义抽象了Bean的注册逻辑
每一个受管的对象在容器中都会由一个BeanDefinition的实例与之对应,该实例负责保存对象的所有必要信息,包括对应对象的class类型,是否是抽象类,构造方法参数以及其他属性等。RootBeanDefinition和ChildBeanDefinition的两个主要实现类
注:单纯的BeanDefinitionRegistory无法强制转换到BeanFactory类型
外部配置文件方式
Spring的IoC容器支持两种配置文件格式:Properties文件格式和XML文件格式
采用外部配置文件时的处理方式:根据不同的外部配置文件格式,给出相应的BeanDefinitionReader实现类,将相应的配置文件内容读取并映射到BeanDefinition,注册到BeanDefinitionRegistry
Properties配置格式的加载
Spring提供了org.springframework.beans.factory.support.PropertiesBeanDefinitionReader类用于Properties格式配置文件的加载
djNewsProvider作为beanName,后面通过.(class)表明对应的实现类是什么。通过在表示beanName的名称后面添加.$[number]后缀的形式,来表示当前beanName对应的对象需要通过构造方法注入的方式注入相关依赖对象。构造方式注入无法通过参数名称来标识注入的确切位置,而setter方法注入则可以通过属性名称来明确标识注入
Spring提供的PropertiesBeanDefinitionReader是按照Spring自己的文件配置规则进行加载的,同样也可以按照自己的规则来提供相应的Properties配置文件
XML配置格式的加载
XML配置格式是Spring支持最完整,功能最强大的表达方式
原因:1、XML具有良好的语意表达能力   2、Spring框架从开始就自始至终保持XML配置加载的统一性
Spring为XML格式的配置文件提供了XmlBeanDefinitionReader,负责读取Spring指定格式的XML配置文件并解析,解析后的文件内容映射到相应的BeanDefinition,并加载到相应的BeanDefinitionRegistry
BeanFactory的XML之旅
XML格式的容器信息管理方式是Spring提供的最为强大、支持最为全面的方式
所有注册到容器的业务对象,在Spring中称之为Bean,每一个对象在XML中的映射对应叫做<bean>的元素,多个<bean>组成<beans>
<beans>是XML配置文件中最顶层元素,相应的属性对所辖的<bean>进行统一的默认行为设置
default-lazy-init:其值可以指定为true或false,默认值为false,用来标志是否对所有的<bean>进行延迟初始化
default-autowire:可以取值为no、byName、byType、construtor、autodetect,默认值为no,如果使用自动绑定的话,用来标志全体 bean使用哪一种默认绑定方式
default-dependency-check:可以取值none,objet,simple,all,默认值为none,即不做依赖检查
default-init-method:如果所管辖的<bean>按照某种规则,都有同样名称的初始化方法的话,可以在这里统一指定这个初始化方法名
default-destory-method:与default-init-mehod相对应,如果所管辖的bean按照某种规则使用了相同名称的对象销毁方法,可以通过这一属性统一指定
id属性
通过id属性来指定当前注册对象的beanName是什么,并非任何情况下都需要指定每个<bean>的id,有些情况下id可以省略
name属性用来指定<bean>的别名
class属性:每个注册到容器的对象都需要通过<bean>元素的class属性指定其类型
构造方法注入的XML之道
按照Spring的IoC容器配置格式,要通过构造方法注入方式,为当前业务对象注入其所依赖的对象,需要使用<constructor-arg>,通过<ref>元素来指明容器将为djNewsProvider这个<bean>注入通过<ref>所引用的Bean实例
type属性:调用第二个传入int类型参数的构造方法,可以使用type属性
index属性:取值从0开始,与一般的数组下标取值相同,指定的第一个参数的index应该是0,第二个参数的index是1,以此类推
setter方法注入的XML之道
与构造方法注入可以使用<constructor-arg>注入配置相对应,Spring为setter方法注入提供了<property>元素
<property>有一个name属性,用来指定该<property>将会注入的对象所对应的实例名称,之后通过value或ref属性或者内嵌其他元素来指定具体的依赖对象引用或值
<property>和<constructor-arg>中可用的配置项
(1)<value>通过value为主体对象注入简单的数据类型,可以指定String类型的数据和Java语言中原始类型以及它们的包装类型
(2)<ref>引用容器中其他的对象实例,通过ref的local、parent、bean属性来指定引用对象的beanName是什么
local:只能指定与当前配置的对象在同一个配置文件的对象定义的名称
parent:只能指定位于当前容器的父类容器中定义的对象引用
bean:基本上通吃,通常情况下直接使用bean来指定对象的引用
(3)<idref>为当前对象注入所以来的对象的名称
(4)内部<bean>将私有的对象仅局限在当前对象,配置只是在位置上有所差异,在配置项上与其他的<bean>没有差别
(5)<list>对应注入对象类型为java.util.List及其子类或者数组类型的依赖对象,通过<list>可以有序地为当前对象注入以collection形式声明的依赖
(6)<set>对应注入Java Collection中类型java.util.set或者其子类的依赖对象,元素的顺序是无关紧要的
(7)<map>与列表(list)使用数字下标来标识元素不同,映射(map)可以通过指定的键(key)来获取相应的值,对应注入java.util.Map或者其子类类型的依赖对象
(8)<props>特殊化的map,对应配置类型为java.util.Properties的对象依赖,每个<props>可以嵌套多个<prop>,通过其key属性来指定键,在<prop>内部直接指定其所对应的值,<prop>内部没有任何元素可以使用,只能指定字符串,由java.util.Properties决定
depends - on :如果classA需要使用log4j,那么就必须在bean定义中使用depends - on来要求容器在初始化自身实例之前首先实例化SystemConfigurationSetup,保证日志系统的可用
autowire
Spring提供了5钟自动绑定模式:no、byName、byType、constructor、autodetect
no:容器默认的自动绑定模式,即不采用任何形式的自由绑定,完全依赖手工明确配置各个bean之间的依赖关系
byName:按类中声明的实例变量的名称,与XML配置中的文件中声明的bean定义的beanName的值进行匹配,相匹配的bean定义被自动绑定到当前实例变量上
byType:容器会根据当前bean定义类型,分析其相应的依赖对象类型,然后到容器所管理的所有bean定义中寻找与依赖对象类型相同的bean定义,然后找到符合条件的bean自动绑定到当前bean定义
constructor:针对构造方法参数的类型而进行的自动绑定,使用上与byType没有太大区别
autodetect:是byType和constructor模式的结合体,如果对象拥有默认无参数的构造方法,容器会优先考虑byType的自动绑定模式
dependency-check:对其所依赖的对象进行最终检查,该功能主要与自动绑定结合,检查每个对象某种类型的所有依赖是否全部注入完成
有如下4钟类型的依赖检查
none:不做依赖检查,跟不指定这个属性等效
simple:容器会对简单属性类型以及相关的collection进行依赖检查,对象引用类型的依赖除外
object:只对对象引用类型依赖进行检查
all:将simple和object相结合,对简单属性类型以及相应的collection和所有对象引用类型的依赖进行检查
继承
parent属性可以与abstract属性相结合,达到相应bean定义模块化的目的;若不想容器在初始化的时候实例化某些对象,可将abstract属性赋值true,以避免容器将其实例化
bean的scope
BeanFactory可以管理对象生命周期;scope用来声明容器中的对象应该处的限定场景或该对象的存活时间
bean的scope类型
singleton:标记为拥有singleton scope的对象定义,在Spring的IoC容器中只存在一个实例,所有对该对象的引用将共享这个实例,从容器启动,到它第一次被请求而实例化开始,只要容器不销毁或退出,该类型bean的单一实例会一直存活
prototype:对于请求方不能共享使用的对象类型,应将其bean定义的Scope设置为prototype
request、session、global session:Spring2.0之后新增加的,只适用于Web应用程序
request:XmlWebApplicationContext会为每个HTTP请求创建新的RequestProcessor对象供当前请求使用,当请求结束后,该对象实例的生命周期即告结束
session:放到session中的最普遍的信息就是用户登录信息,Spring会为每个独立的session创建属于自己的全新UserPreferences对象实例
global session:应用在基于portlet的web应用程序中才有意义,映射到portlet的global范围的session
工厂方法与FactoryBean
工厂方法模式:提供一个工厂类来实例化具体的接口实现类,主体对象只需依赖工厂类,不需做任何改变
静态工厂方法:<bean id = "bar" class = "...StaticBarInterfaceFactory" factory-method = "getInstance/">
class指定静态方法工厂类,factory-method指定工厂方法名称,容器调用该静态方法工厂类的指定工厂方法(getInstance),并返回方法调用后的结果,即BarInterfaceImpl的实例
非静态工厂方法:NonStaticBarInterfaceFactory是作为正常的bean注册到容器的,使用factory-bean属性来指定工厂方法所在的工厂类实例,也是通过factory-method指定工厂方法名称
FactoryBean:Spring容器提供的一种可以扩展容器对象实例化逻辑的接口(BeanFactory是一种容器)
偷梁换柱之术
方法注入:让getNewsBean方法声明符合规定的格式,并在配置文件中通知容器,当该方法被调用的时候,每次返回指定类型的对象即可
使用BeanFactoryAware接口:Spring框架提供了一个BeanFactoryAware接口,容器在实例化实现了该接口的bean定义的过程中,会自动将容器本身注入该bean
使用ObjectFactoryCreatingFactoryBean:Spring提供的一个FactoryBean实现,返回一个ObjectFactory实例,可以返回容器管理的相关内容,隔离了客户端对象对BeanFactory的直接引用
方法替换:可以灵活替换或者说以新的方法覆盖掉原来某个方法的实现逻辑,帮助实现简单的方法拦截功能
容器背后的秘密
Spring的IoC容器的作用:以某种方式加载Configuration Metadata(通常也就是XML格式的配置信息),然后根据这些信息绑定整个的系统对象,最终组装成一个可用的基于轻量级容器的应用系统,分为两个阶段:1、容器启动阶段 2、Bean实例化阶段
容器启动阶段:首先会通过某种途径加载 Configuration Metadata,大部分情况下,容器需要依赖某些工具类(BeanDefinitionReader)对加载的 Configuration Metadata进行解析和分析,将分析后的信息编组为相应的BeanDefinition,最后将这些保存了bean定义必要信息的BeanDefinition注册到相应的BeanDefinitionRegistry
Bean实例化阶段:容器首先检查所请求对象之前是否已经初始化,如果没有,根据注册的BeanDefinition提供的信息实例化被请求对象,并为其注入依赖    ;如果该对象实现了某些回调接口,也会根据回调接口的要求进行装配,当对象装配完毕之后,容器会立即将其返回请求方使用
Spring IoC容器  ApplicationContext
Spring框架内部使用org.springframework.core.io.Resource接口作为所有资源的抽象和访问接口
Resource:可以根据资源的不同类型,给出相应的具体实现
ByteArrayResource:将字节数组提供的数据作为一种资源进行封装,如果通过IntputStream形式访问该类型的资源,该实现会根据字节数组的数据构造相应的ByteArrayInputStream并返回
ClassPathResource:该实现从Java应用程序的ClassPath中加载具体资源并进行封装,可以使用指定的类加载器或给定的类进行资源加载
FileSystemResource:对java.io.File类型的封装,可以以文件或URL的形式对该类型资源进行访问
UrlResource:通过java.net.URL进行的具体资源查找定位的实现类,内部委派URL进行具体的资源操作
可用的ResourceLoader
DefaultResourceLoader
(1)首先检查资源路劲是否以classpath前缀打头,如果是,则尝试构造ClassPath-Resource类型资源并返回
(2)否则,尝试URL,根据资源路径来定位资源,如果没有抛出Malformed-URLException,有则会构造UrlResource类型的资源并返回
FileSystemResourceLoader
继承自DefaultResourceLoader,但覆写了getResourceBypath(String)方法,使之从文件系统加载资源并以FileSystemResource类型返回
ResourcePatternResolver ---批量查找的ResourceLoader
ResourcePatternResolver是 ResourceLoader的扩展, ResourceLoader每次只能根据资源路径返回确定的单个Resource实例,而 ResourcePatternResolver可以根据指定的资源路径匹配模式每次返回多个Resource实例
ResourcePatternResolver最常用的一个实现org.springframework.core.io.support.PathMatching ResourcePatternResolver,该实现类支持ResourceLoader级别的资源加载,支持基于Ant风格的路径匹配模式,支持 ResourcePatternResolver新增加的classpath*前缀等
一起来看AOP(AOP是一种理念)
AOP:对系统需求进行模块化的组织,简化系统需求和现实之间的对比关系,进而使得整个系统的实现更具模块化
静态AOP优点:Aspect直接以Java字节码的形式编码到Java类中,Java虚拟机可以像通常一样加载Java类运行,不会对整个系统的运行造成任何性能损失
动态代理:可以在运行期间为相应的接口(Interface)动态生成对应的代理对象,所有需要织入横切关注点逻辑的模块类都得实现相应的接口,因为动态代理机制只针对接口有效
自定义类加载器
所有Java程序的class都要通过相应的类加载器加载到Java虚拟机之后才可以运行,可以通过自定义类加载器的方式完成横切逻辑到系统的织入,通过读取外部文件规定的织入规则和必要信息,在加载class文件器件就可以将横切逻辑添加到系统模块类的现有逻辑中,将改动后的class交给java虚拟机运行
常见Joinpoint(执行时点)类型
方法调用:某个方法被调用的时候所处的程序执行点
方法执行:某个方法内部执行开始时点
方法调用是在调用对象上的执行点,方法执行则是在被调用的方法逻辑执行的时点,对于同一对象,方法调用要先于方法执行
Pointcut
Pointcut是Joinpoint的表述方式,将横切逻辑织入当前系统的过程中,需要参照Pointcut规定的Joinpoint信息,才知道应该往系统的哪些Joinpoint上织入横切逻辑
Pointcut的表述方式:较为普遍的Pointcut表达方式,可以充分利用正则表达式的强大功能,来归纳表述需要符合条件的多族Joinpoint
直接指定Joinpoint所在方法名称:表述方式比较简单,而且功能单一,通常只限于支持方法级别Joinpoint的AOP框架
使用特定的Pointcut表述语言:最为强大的表述Pointcut方式,灵活性也好,但具体实现起来会过于负责,需要设计该表述语言的语法,实现相应的解释器等许多工作
Advice
单一横切关注点逻辑的载体,代表将会织入到Jointpoint的横切逻辑
Before Advice:在Joinpoint指定位置之前执行的advice类型,通常不会中断程序执行流程,必要时利用抛出异常的方式来中断当前程序流程
After Advice:在连接点之后执行的Advice类型
After returning Advice:当前Joinpoint处执行流程正常完成后,才会执行
After throwing Advice:当前Joinpoint出执行过程抛出异常情况,才会执行
After Finally Advice:无论正常终了还是抛出异常,都会执行
Around Advice:对附加其上的Jointpoint进行“包裹”,可以在Joinpoint之前和之后都指定相应的逻辑,可以自然完成Before Advice和After Advice的功能
Introduction:不是根据横切逻辑在Joinpoint处的执行时机来区分的,而是根据可以完成的功能而区别于其他的Advice类型,可以为原有的对象添加新的特性或行为
Aspect:系统中的横切逻辑关注点逻辑进行模块化封装的AOP概念实体
目标对象:符合Pointcut所指定的条件,将在织入过程中被织入横切逻辑的对象
Spring AOP概述:可以更快捷地融入开发过程
设计模式之代理模式
代理机制的实现有现成的设计模式的支持,叫代理模式
ISubject:该接口是对被访问者或访问资源的抽象  SubjectImpl:被访问者或被访问资源的具体实现类
SubjectProxy:被访问者或访问资源代理实现类,该类持有一个ISubject接口的具体实现
Client:代表访问者的抽象角色,将会访问ISubject类型的对象或资源
动态代理
可以为指定的接口在系统运行期间动态生成代理对象;在InvocationHandler的基础上细化程序结构,并根据Advice类型分化出不同Advice类型的程序结构
动态字节码的生成:对目标对象进行继承扩展,为其生成相应的子类,子类通过覆写来扩展父类的行为,将横切逻辑的实现放到子类中,让系统使用扩展后的目标对象的子类
Spring AOP的Pointcut
Spring中以接口定义org,springframework.aop.Pointcut作为AOP框架中所有Pointcut的最顶层抽象,该接口定义了两个方法用来帮助捕捉系统中相应的Joinpoint,并提供了一个TruePointcut类型实例
常见的Pointcut
NameMatchMethodPointcut:可以根据自身指定的一组方法名称与Joinpoint处的方法的方法名称进行匹配
per15RegexpMethodPointcut和JdkRegexpMethodPointcut
可以通过pattern或patterns对象属性指定一个或多个正则表达式的匹配模式,指定的正则表达式匹配模式应该覆盖匹配整个方法签名,而不是只指定到方法名称部分
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值