《Spring 揭秘》读书笔记

《Spring 揭秘》读书笔记

豆瓣评分:9.1 分。书是 2009 年出版的,使用的 Spring 版本应该是 2.5,比较老了,不过思想一流。

IoC 章节

装修新房,需要用家具,我们要么 new,多数情况下还是我们自己去家具厂将家具买回来,有一个共同点就是我们都是自己主动去获取依赖的对象IoC 的理念,让别人为你服务

如何暗示对方你需要什么样的适当的服务?构造方法注入:构造方法中声明依赖对象的参数列表;Setter 注入:更为宽松随意;接口注入:自己需要实现某个接口来进行暗示,已经不流行了。

IoC Service Provider 的职责:业务对象的构建管理、业务对象间的依赖绑定。如何管理对象间的依赖关系:直接编码、XML 配置文件等方式来记录对象间的关系。

Spring 的 Ioc 容器类型:BeanFactoryApplicationContext,其中 ApplicationContext 更为高级,比如事件发布、国际化信息支持等。BeanFactory 像是一个汽车生产厂,其他零件厂商送入零件放入这个汽车工厂,只需要从终点获得成品汽车 Object getBean(String name) 就可以了,我们需要交给它一份生产图纸 (XML 配置文件)。

BeanFactory 只是一个接口,好比我们跟图书馆打交道,书本实际上是放置在书架 BeanDefinitionRegistry 上的,每一本书都有一个 BeanDefinition 与之相对应。

虽然 lazy-init-bean 是延迟初始化的,但是因为依赖它的 not-lazy-init-bean 并不是延迟初始化的,所以还是会被提前初始化。所以需要保证依赖于该 bean 定义的其他 bean 定义也同样设置为延迟初始化:<beans default-lazy-init="true">

prototype 生命周期,当对象实例返回给请求方之后,就任由这个对象自生自灭了,需要请求方自己负责这个对象的后续生命周期的管理工作。

FactoryBean 是 Spring 容器提供的一种可以扩展容器对象实例化逻辑的接口,其主语是 Bean,它是生产对象 getObject() 的工厂。某些对象的实例化逻辑过于繁琐,或者第三方库不能直接注册到 Spring 容器的时候,就可以实现 FactoryBean 接口,给出自己的对象实例化逻辑代码。

Spring 的 Ioc 容器启动的流程分为:容器启动阶段(装配生产线:依赖 BeanDefinitionReader 解析,编组为 BeanDefinition,最后将其注册到 BeanDefinitionRegistry 中)和 Bean 实例化阶段(getBean 方法:装配好的生产线生产具体的产品)。

Bean 的实例化过程:

ApplicationContext 间接继承了 ResourceLoader,提供统一的资源加载策略。继承了 MessageSource 统一了国际化信息的访问方式。Spring 的 ApplicationContext 容器内部允许以 ApplicationEvent 的形式发布事件,容器内注册的 ApplicationListener 类型的 bean 定义会被 ApplicationContext 容器自动识别,它们负责监听容器内发布的所有 ApplicationEvent 类型的事件。也就是说,一旦容器内发布 ApplicationEvent 及其子类型的事件,注册到容器的 ApplicationListener 就会对这些事件进行处理。

AOP 章节

AOP 世界的公民:Joinpoint 表示程序执行的时机。Pointcut 表示 Joinpot 的表述方式。Advise 是单一横切关注点逻辑的载体。各种 Advise 执行时机:

Java 动态代理实现 InvocationHandlerinvoke 方法即可,不过其只能对实现了相应接口的类使用。如果某个类没有实现任何接口,那么其会使用 CGLIB 开源动态字节码类库,为目标对象生成动态的代理对象实例。其原理是对目标对象进行继承扩展,生成子类,通过覆写来扩展父类的行为。其唯一限制就是无法对 final 方法进行覆写。

同一 Joinpot 的多个 Advisor ,按照顺序号来依次执行,顺序号越小,优先级越高。小于 0 的原则上是 Spring AOP 内部使用。

execution 的格式如下:

execution(修饰符? 返回类型 declaring-type-pattern? 方法名(方法参数) 抛出异常的模式?)

方法的返回类型、方法名以及参数部分的匹配模式必须指定。

* 可以用于任何部分的匹配模式,.. 可以在declaring-type-pattern 和参数匹配模式的位置使用。

// 只能指定 cn.spring21 这一层下的所有类型
execution(void cn.spring21.*.doSomething(*))
// .. 指定多个层次
// 匹配 cn.spring21 包下的所有类型
// 以及 cn.spring21 下层包下声明的所有类型
execution(void cn.spring21..*.doSomething(*))
// 0 到多个参数
execution(void *.doSomething(..))
// 第一个参数String,第二个参数类型不限
execution(void doSomething(String,*))
// 前面几个参数类型不限制,但是最后一个必须是String
execution(void doSomething(..,String))

within 只接受类型声明:

// 匹配 MockTarget 类的所有方法声明
within(cn.spring21.aop.target.MockTarget)
// 匹配 cn.spring21.aop.target 包下所有类型的内部的方法级别的 Joinpoint
within(cn.spring21.aop.target.*)
// 匹配 cn.spring21.aop.target 包下以及子包所有类型的内部的方法级别的 Joinpoint
within(cn.spring21.aop..*)

args 捕捉拥有指定参数类型、参数数量的方法级 Joinpot:

// 匹配 Foo 类的 login(User user) {} 方法
// 也匹配 Bar 类的 isLogin(User user) {} 方法
args(cn.spring21.abc.domain.User)

args 方法是在运行期间动态检查参数的类型,即时目标方法是 login(Object user),只要传入的是 User 类型,那么依然可以捕捉到。

@annotation 检测所有含有某个注解的方法。

AOP 应用案例:异常处理、安全检查、缓存。