一.Spring简介
1.Spring是一个开源框架, 是为了解决企业级应用开发的复杂性而创建的, 最初创建Spring的主要目的是用来替代更加重量级的企业级Java技术, 尤其是EJB (企业级JavaBean, Enterprise JavaBean). 相对于EJB来说, Spring提供了更加轻量级和简单的编程模型. 增强了简单老式Java对象 (POJO) 的功能, 使之具备了之前只有EJB和其他企业级Java规范才具有的功能.
Spring最根本的使命: 致力于简化企业级Java开发,促进代码的松散耦合. 成功的关键在于依赖注入和AOP.
为了降低java开发的复杂性, Spring采取了4种关键策略:
(1)基于POJO的轻量级和最小侵入性编程.
(2)通过依赖注入和面向接口实现松耦合.
(3)基于切面和惯例进行声明式编程.
(4)通过切面和模板减少样板式代码.
几乎Spring所做的任何事都可以追溯到上述的一条或多条策略.
2.Spring模块
Spring框架关注于通过DI (依赖注入IoC), AOP (面向切面编程)和消除样板式代码来简化企业级Java开发. 但在Spring框架之外还存在一个构建在核心框架之上的庞大生态圈, 它将Spring扩展到不同的领域, 例如 Web服务, REST, 移动开发以及NoSQL.
Spring框架的发布版本包括了20个不同的模块, 每个模块会有3个JAR文件 (二进制类库, 源码的JAR文件以及JavaDoc的JAR文件) 这些模块依据所属的功能可以划分为6类不同的功能.
Spring框架由6个定义良好的模块分类组成.
对Spring六大模块进行简单描述:
(1)Spring核心容器
容器是Spring框架最核心的部分, 它管理着Spring应用中bean的创建, 配置和管理. 所有Spring模块都构建于核心容器之上.
(2)Spring的AOP模块
在AOP模块中, Spring对面向切面编程提供了丰富的支持. 这个模块是Spring应用系统中开发切面的基础.
(3)数据访问与集成
Spring的JDBC和DAO模块抽象了数据库连接等样板式代码, 使数据库的访问变得简单明了, 方便了对数据库的操作.
(4)Web与远程调用
MVC (Model-View-Controller)模式是一种普遍被接受的构建Web应用的方法, 它可以帮助用户将界面逻辑与应用逻辑分离. Java从不缺少MVC框架, Apache的Struts, JSF, WebWork都是可选的最流行的MVC框架. 虽然Spring能够与多种流行的MVC框架进行集成, 但它的Web和远程调用模块自带了一个强大的MVC框架. 有助于在Web层提升应用的松耦合水平.
(5)Instrumentation
Spring的Instrumentation模块提供了为JVM添加代理的功能.
(6)测试
Spring提供了测试模块以致力于Spring应用的测试.
二.依赖注入
IoC又称为DI
DI: Dependency Injection 依赖注入,又称为IoC(控制反转)
任何一个有实际意义的应用都会有两个或者更多的类组成, 这些类互相之间协作来完成特定的业务逻辑. 每个对象负责管理与自己相互协作的对象 (即它所依赖的对象) 的引用.
在Knight的构造函数里自行创建了QuestImpl, 使得Knight与QuestImpl紧耦合到了一起.
耦合具有两面性. 一方面, 紧密耦合的代码难以测试, 难以复用, 难以理解. 但是为了完成有实际意义的功能, 不同的类必须以适当的方式进行交互, 总而言之, 耦合是必须的, 但应当小心谨慎地管理.
通过DI, 对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定, 对象无需自行创建或者管理它们的依赖关系, 依赖关系将自动被注入到需要它们的对象中去.
Quest通过Knight的构造方法被注入进来, 这是依赖注入的方式之一, 即构造器注入. 这里的要点是Knight没有与任何特定的Quest实现发生耦合, 这就是DI带来的最大收益-------松耦合.
依赖注入的三种方式:
1.构造器注入
2.setter方法注入
3.注解注入
三.Spring-------装配Bean
1.容纳Bean (Spring的IoC容器)
在基于Spring的应用中, 应用对象生存于Spring容器中(container). Spring容器负责创建对象, 装配对象, 配置它们并管理它们的整个生命周期. 从生存到死亡. 容器是Spring的核心框架, Spring IoC容器使用DI管理构成应用的组件, 它会创建相互协作的组件之间的关联. Spring容器并不是只有一个, Spring自带了多个容器实现, 可以归纳为两种不同的类型. bean工厂(由org.springframework.beans.factory.BeanFactory接口定义) 是最简单的容器, 提供基本的DI支持. 应用上下文(由org.springframework.context.ApplicationContext接口定义) 基于BeanFactory构建, 并提供应用框架级别的服务.
org.springframework.beans 和 org.springframework.context 包是Spring 框架 Ioc容器的基础.
在Spring中, 被Spring IoC容器管理的这些来自于应用主干的这些对象称为beans. bean是一个由Spring IoC容器进行实例化, 装配和管理的对象.
2.使用应用上下文 (Spring IoC容器)
Spring通过应用上下文(Application Context)装载bean的定义并把他们组装起来. Spring应用上下文全权负责对象的创建和组装. Spring自带了多种应用上下文的实现, 它们之间的主要区别仅仅在于如何加载配置.
3.bean的装配
创建应用对象之间协作关系的行为通常称为装配(wiring), 这也是依赖注入的本质.
Spring提供了三种主要的装配机制:
(1)在XML中进行显式配置;
(2)在Java中进行显式配置;
(3)自动化装配(使用注解进行装配)
4.实现自动化装配bean
Spring的自动化装配提供了很大的便利性.
Spring从两个角度来实现自动化装配:
(1)组件扫描: Spring会自动发现应用上下文中所创建的bean.
(2)自动装配: Spring自动满足bean之间的依赖.
-----------------------------------------------------------------------------------------------------------------------------
1.组件扫描:
@Component注解的使用
在Compact这个类上使用的@Component注解, 这个注解表明该类会作为组件类, 告知Spring要为这个类创建bean.
不过, 组件扫描默认是不启用的, 还需要显示配置一下Spring, 从而命令它去寻找带有@Component注解的类, 并为其创建bean.
@ComponentScan注解的使用(开启组件扫描)
JavaConfig类使用了@ComponentScan注解, 这个注解能够在Spring中启用组件扫描. @ComponentScan默认会扫描与配置类相同的包. 从而查找带有@Component的类, Spring中自动为其创建一个bean. (JavaConfig和Compact类处于同一个包中)
还可以使用XML来启用组件扫描
测试以上注解方法
这是一个测试类. Test类使用了Spring的SpringJUnit4ClassRunner, 在测试开始的时候自动创建Spring应用上下文. 注解@ContextConfiguration会告诉它要在JavaConfig中加载配置, 最终的上下文应该包含 Compact bean.
测试代码中有一个Compact类型的属性, 带有@Autowired注解以便于将Compact bean注入到测试代码中. 在测试方法中用Compact类型的属性调用方法, 测试成功, 表明它不为null, 意味着Spring能够发现 Compact 类, 自动在Spring应用上下文中将其创建为bean 并将其注入到测试代码中.
2.为组件扫描的bean命名
Spring 应用上下文中所有的bean都会给定一个ID. 如果没有明确地设置ID, Spring会将其类名第一个字母变为小写, 并且指定为该bean的ID.
使用@Component注解就可以为Student类指定一个ID. 同样可以使用@Named注解来代替@Component注解.
3.设置组件扫描基础包
@ComponentScan 注解会以它所表示的配置类所在的包作为默认基础包来扫描组件.
为组件扫描设置基础包:
@ComponentScan("com.demo.spring") 会扫描所指定的com.demo.spring这个包.
@ComponentScan(basePackages={"com.demo.index","com.demo.mvc"})会扫描所指定的多个包.
将基础包以String类型表示, 不利于代码的重构. 可以将其指定为包中所包含的类或接口.
@ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class}) basePackages属性换成了basePackageClasses. 为basePackageClasses属性所设置的数组中包含了类. 这些类所在的包将会作为组件扫描的基础包.
4.自动装配
很多bean只有依赖其他对象才能完成调试, 所以要将组件扫描所得到的bean和其他对象装配到一起.
自动装配就是让Spring自动满足bean依赖的一种方法, 在满足依赖的过程中, 会在Spring应用上下文中寻找匹配某个bean需求的其他bean. @Autowired注解实现了自动装配.
@Autowired注解可以用在构造器, setter方法,或者直接用在属性上. 在Spring初始化bean之后, 它会尽可能满足bean的依赖, 依赖则是带有@Autowired注解的方法进行声明的. 有且只有一个bean匹配依赖需求的话, 那么这个bean将会被装配进来.
如果没有匹配的bean, 在创建应用上下文时, Spring 会出现一个异常. 为了避免异常, 可以将@Autowired的required属性设值为false; 则装配时没有匹配的bean时, Spring会让这个bean处于未装配状态. 这个不安全, 会出现NullPointerException异常.
在自动装配中, Spring支持@Autowired和@Inject. 可以相互替换.
5.通过Java代码装配bean
@Configuration注解表明这个类是一个配置类, 包含在Spring IoC容器如何创建bean的细节.
@Bean 注解告诉Spring这个方法将返回一个对象, 该对象要注册为Spring应用上下文中.
默认情况下, bean的ID与带有@Bean注解的方法名一样. 也可以为其设置成不同的名字 @Bean(name="gth").
-------------------------------------------------------------------------------------------------------------------------------------------------
借助JavaConfig配置类实现注入
getTeacher()方法会创建一个bean实例并将其注册到 IoC容器中. 通过Teacher类的构造器将Student类对象注入进去.
看起来是Stduent是通过调用getStudent()得到的, 其实是Spring 会拦截对它的所有调用, 确保直接返回该方法所创建的bean.而不是每次都对它进行实际的调用. 默认情况下, Spring中的bean都是单例.
udent
也可以通过上述这种方法, 将Student bean 注入到Teacher bean 中去, 当Spring调用getTeacher()创建 Teacher bean时, 会自动装配一个Student注入到Teacher构造器中, 而不用明确引用Student的@Bean方法.
6.通过XML装配bean
在基于XML的Spring配置中声明一个bean, 要使用spring-beans模式中的一个元素:<bean>
1.构造器注入初始化bean
(1)构造器注入bean引用
Spring遇到bean元素会创建一个Teacher实例, <constructor-arg>元素会告知Spring要将一个ID为stu的Stduent 的bean引用传递到Teacher构造其中.
在Spring3.0中引入了 c-命名空间, 更简洁的描述构造器参数.
必须在XML的顶部声明其模式
属性名以" c: "开头, 表示命名空间的前缀.
"-0" 表示参数的索引 (如果只有一个构造器且只有一个参数,则可省去下标0)
"-ref" 表明正在装配的是一个引用.
(2)构造器注入字面常量
使用c-命名空间
(3)装配集合
c-命名空间无法实现集合的装配
2.Setter方法实现属性注入
p-命名空间可以用来代替<property>属性
启用p-命名空间, 必须在XML文件中对其进行声明:
"p:" 表示命名空间前缀
name: 属性名
"-ref" 表示Spring要进行装配的是引用, 而不是常量
不能使用p-命名空间来装配集合, 但是可以使用 util-命名空间, 再将集合引用通过p-命名空间来装配
先对 util-命名空间进行模式声明