一、Spring 框架概述1. Spring 框架的作用Spring 框架的作用就是为了代码的“解耦”为了降低代码之间的耦合度。根据功能不同可以将系统中的代码分为主业务逻辑代码和交叉业务逻辑代码主业务逻辑代码有具体的专业业务应用场景复用性比较低。交叉业务逻辑代码没有专业业务应用场景主要是为主业务逻辑提供系统级的服务例如日志、安全、事务等等复用性比较强。2. Spring 框架降低耦合度的方式Spring 框架降低耦合度的方式分为两种控制反转 (IoC)和面向切面编程 (AOP)。IoC主业务逻辑在相互调用的过程中不再自己去创建要使用的对象而是由 Spring 容器统一管理在主业务逻辑需要的时候自动“注入”给主业务逻辑。AOP使得交叉业务逻辑得到最大的复用且交叉业务逻辑不会混杂在主业务逻辑中而是由 Spring 容器统一完成”织入“。3. Spring 的体系结构Spring 由 20 多个模块组成它们可以分为数据访问/集成 (Data Access/Integration)、Web、面向切面编程 (AOP、Aspect)、用于服务器设备管理 (Instrumentation)、消息发送 (Messaging)、核心容器 (Core Container) 和 测试 (Test)。4. Spring 的下载Spring 官网http://spring.io5. Spring 的特点(1) 非侵入式Spring 框架的 API 不会出现在主业务逻辑代码中即主业务逻辑代码是一个普通的 Java 类 (pojo)可以快速移植到其他框架。(2) 容器Spring 作为一个容器可以管理对象的生命周期、对象与对象之间的依赖关系可以通过配置文件来定义对象以及设置对象与对象之间的关系。(3) IoC (控制反转)创建被调用的实例不是由调用者完成而是由 Spring 容器完成然后注入给调用者。这样就降低了主调方和被调方的耦合度。举个例子// 传统的做法main(){// 主调方法 main() 和被调方 Student 对象耦合在一起了Student student new Student();student.show();}// Spring 的 IoC将 student 对象配置到 Spring 容器中main() {// 从 Spring 容器中获取 student 对象降低了代码之间耦合度student.show();}(4) AOP (面向切面编程)是一个编程思想是对面向对象编程的补充。通过分离主业务逻辑和交叉业务逻辑将复用性比较高的日志、安全、事务等单独写在一个称为“切面”的类中。在需要时将”切面“动态的“织入”到主业务逻辑中降低代码的耦合性。二、Spring 与 IoC1. IoC 实现方式IoC 是一个概念也是一种思想其实现方式有多个目前比较流行的(1) 依赖查找 (DL, Dependency Lookup)容器提供回调接口和上下文环境给组件程序代码则需要提供具体的查找方式。典型的应用就是 JNDI 系统查找应用不多。(2) 依赖注入 (DI, Dependency Injection)程序代码不做定位查询由外部容器自己完成。依赖注入是目前最优秀的解耦方式。2. 开发第一个 Spring 应用 (DI 的体现)(1) 导入 Spring 的基础 jar 包包含 beans、core、context、expression 以及依赖库 commons-logging还可以引入 log4j 日志包和 junit 测试包。(2) 定义主业务逻辑接口和实现类接口package com.edu.service; public interface IStudentService { void show(); }实现类package com.edu.service.impl; import com.edu.service.IStudentService; public class StudentServiceImpl implements IStudentService { Override public void show() { System.out.println(我是一个学生); } }(3) 创建 Spring 的主配置文件在src或resources目录下创建applicationContext.xml?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beans xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:contexthttp://www.springframework.org/schema/context xsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd bean idstudentService classcom.edu.service.impl.StudentServiceImpl/ /beans(4) 测试类package com.edu.test; import com.edu.service.IStudentService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MySpringTest { Test public void testFirstSpringApp(){ // 1. 读取 Spring 的主配置文件获取 Spring 的容器ApplicationContext ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml); // 2. 从容器中获取 bean 对象 IStudentService studentService context.getBean(studentService, IStudentService.class); studentService.show(); } }3. ApplicationContext 容器ApplicationContext用于加载核心配置文件充当“容器”的角色其常用实现类有ClassPathXmlApplicationContext配置文件在类路径下 (src或resources目录)。FileSystemXmlApplicationContext配置文件在本地磁盘目录中或项目的根路径下。4. BeanFactory 接口容器BeanFactory是ApplicationContext的父接口也可以作为 Spring 容器其实现类有XmlBeanFactory。需要将配置文件以Resource形式传递Test public void testBeanFactory(){ BeanFactory factory new XmlBeanFactory(new ClassPathResource(applicationContext.xml)); IStudentService studentService factory.getBean(studentService, IStudentService.class); studentService.show(); }ApplicationContext 和 BeanFactory 的区别ApplicationContext容器创建时就已经将对象装配好。执行效率高比较占内存空间换时间。BeanFactory采用延迟装配策略第一次调用getBean()时才去装配对象。节约内存响应速度慢时间换空间。注意Spring 容器在装配 bean 对象时默认调用无参构造方法。5. Bean 的装配(1) 默认装配方式调用 bean 的无参构造器创建空值对象。(2) 动态工厂 Bean利用 Spring 提供的factory-bean和factory-method属性bean idfactory classcom.edu.utils.ServiceFactory/ bean idstudentService factory-beanfactory factory-methodgetStudentService/(3) 静态工厂 bean无需工厂实例直接通过工厂类的静态方法创建bean idstudentService classcom.edu.utils.ServiceFactory factory-methodgetStudentService/(4) 容器中 bean 的作用域 (scope)作用域说明singleton默认值。单例模式整个容器中只有一个实例。非线程安全prototype原型模式。每次getBean()都会创建一个新的实例。延迟加载线程安全requestWeb 应用中每次 HTTP 请求产生一个不同的 bean 对象。sessionWeb 应用中每次 HTTP 会话产生一个不同的 bean 对象。global sessionWeb 集群应用中全局 HTTP 会话对应一个 bean 对象。(5) Bean 后处理器 (BeanPostProcessor)是一个特殊的 bean容器初始化 bean 时自动执行该类的前置和后置方法常用于结合 JDK 动态代理对目标 bean 进行增强。(6) 定制 bean 的生命周期通过init-method和destroy-method属性指定初始化和销毁方法bean idsomeService classcom.edu.service.impl.SomeServiceImpl init-methodsetUp destroy-methodtearDown/三、基于 XML 配置的 DI依赖注入1. 设值注入 (setter 注入)要求 bean 必须有默认构造方法和对应属性的 setter 方法。基本类型注入使用property name... value.../域属性注入 (对象引用)使用property name... ref.../bean idschool classcom.edu.beans.School property nameid value10011/ property namename value清华大学/ /bean bean idstudent classcom.edu.beans.Student property nameid value11011/ property namename value小明/ property nameschool refschool/ /bean2. 构造注入要求 bean 必须有全参构造函数。bean idstudent classcom.edu.beans.Student constructor-arg nameid value100011/ constructor-arg namename value娜娜/ constructor-arg nameschool refschool/ /bean3. 集合属性的注入支持数组array、Listlist、Setset、Mapmap和 Propertiesprops的注入。property namestudents list ref beanstudent1/ ref beanstudent2/ /list /property4. 对域属性的自动注入 (autowire)byName根据域属性的名称和 Spring 容器中 bean 的 id 匹配注入。byType根据类型同源相同类型或其子类/实现类自动匹配注入。注意容器中同源的 bean 只能有一个。5. 使用 SPEL 注入Spring EL 表达式语法#{...}property namepersonAge value#{T(java.lang.Math).random()*30}/ property nameempName value#{person.personName.toString()}/6. 使用抽象 bean 注入使用abstracttrue标记父 bean子 bean 使用parent父bean的id继承属性减少冗余配置。7. 多配置文件加载可以使用import resourcespring-*.xml/在总配置文件中引入其他子配置文件。四、基于注解的 DI (依赖注入)开启注解扫描 (需引入 AOP 包)context:component-scan base-packagecom.edu.beans/context:component-scan1. 常用创建对象的注解Component通用组件注解。Repository用于 Dao 层。Service用于 Service 层。Controller用于 Web 控制层。2. 属性注入注解Value注入基本数据类型。Autowired按类型自动注入域属性。Qualifier(beanId)配合Autowired实现按名称注入。Resource默认按类型注入Resource(namebeanId)按名称注入。3. 其他相关注解Scope(prototype)设置作用域。PostConstruct初始化方法。PreDestroy销毁方法。4. JavaConfig 配置类使用Configuration标注配置类Bean标注向容器注册对象的方法。Configuration public class DataSourceConfig { Bean(name dataSource) public DataSource dataSource(){ return new DataSource(com.edu.jdbc.Driver,jdbc:mysql://localhost:3306/test,root,root); } }5. Spring Test 整合 JUnitRunWith(SpringRunner.class) ContextConfiguration(locations classpath:applicationContext.xml) public class SpringTest { Autowired private IUserService userService; // ... Test methods }