1. Spring介绍
- 1.认识Spring-(Spring的核心:IOC/DI AOP) 面试;
- 2.运行Spring;(掌握)快速的搭建Spring Spring框架快速的集成到你的项目
- 3.BeanFactory与ApplicationContext的认识;(掌握 面试)
- 4.Spring注解测试;(掌握)
- 5.Spring中的Bean的细节;(掌握)
- 6.三层架构(service); 面试题
- 7.配置依赖注入;(掌握)--在以后使用Spring的过程中
- 初识Spring
2.1. 什么是Spring
解释:Spring是一个轻量级的DI(Ioc)和AOP的容器框架
存在的目的:创建轻量级的J2EE应用
注:spring是轻量级的J2EE应用,而标准的J2EE是EJB(难)那一套东西
轻量级:应用大小和应用开支,包括应用方式 |
DI(IOC):Spring通过一种称作控制反转(IoC)的技术促进了低耦合 |
AOP:切面编程将业务逻辑从应用服务中分离 |
容器:包含并管理应用对象的生命周期和配置 |
框架:使用组件配置组合成复杂的应用,并提供很多基础功能 |
Spring致力于J2EE应用的各层的解决方案,而不是仅仅专注于某一层的方案。可以说Spring是企业应用开发的“一站式”选择,并贯穿表现层、业务层及持久层。然而,Spring并不想取代那些已有的框架,而是与它们无缝地整合。
Spring提供了对开源社区中很多框架及JavaEE中很多技术的支持,让程序员很轻松能整合及使用这些框架技术。
Spring以一种非侵入式的方式来管理你的代码,Spring提倡”最少侵入”,这也就意味着你可以适当的时候安装或卸载Spring(配置文件配置 或是修改)。
面向对象(对象更适合人的思想-依赖类) -> 面对接口(解耦-依赖接口) -> 面向工厂(再解耦-依赖工厂) -> Spring工厂(花式创建对象,随时可卸载)
2.7. Spring核心与模块化
2.7.1. 依赖注入(DI)/控制反转(IOC)
我们前面说过,Spring是一个DI(Ioc)和AOP的容器框架
IOC与DI 对应着Spring的容器,而这两个概念是一回事
IOC(Inverse of control):控制反转
以前service需要一个dao,需要自己去控制整dao的生命周期(自己创建,销毁等),但是现在service依赖于dao,但是它不负责去管理这个dao的生命周期(不是自己创建,销毁)。相于把以前自己对dao的控制权反转到了容器中(Spring)
DI(Dependence inject):依赖注入
依赖关系由容器注入
控制反转?
谁控制谁 Spring控制对象的实例化以及对象与对象之间的关系
正转 代码中直接对象的实例化
依赖注入?
谁依赖谁 对象的实例化依赖于Spring
谁注入谁 Spring将程序中某些对象需要依赖的对象注入
总结:对象的关系依赖于容器注入,由容器管理,对象自己不需要管理
2.7.2. AOP(面向切面编程)
我们前面说过,Spring是一个DI(Ioc)和AOP的容器框架
AOP即面向切面
扩展阅读解释 |
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 |
可以用于:日志记录,性能统计,安全控制,事务处理,异常处理等等 |
Spring使用AOP的功能完成各种共用的模板功能,使得我们的业务代码与其它代码分开
面试题:介绍一下Spring的理解
DI/IOC
AOP
容器
2.11. Spring的模块化
Spring3.0 之后,就根据模块化的形式进行开发:
注:Spring所有的其它功能都是基于容器。 如它帮我们写Hibernate的事务等模板代码,我们总得把Hibernate交给它管理吧
2.12. 第三步:小结(突出重点)、使用场景、注意点
Spring是一个轻量级的DI(IOC)与AOP的容器框架
百度(重量级):EJB 企业JavaBean
DI:依赖注入 = IOC控制反转
谁依赖谁:对象的实例化和对象之间的关系 依赖Spring
谁注入谁:Spring注入需要的对象
谁控制谁:Spring控制对象的实例化以及管理
容器的概念:将需要的对象交给Spring来管理
AOP:面向切面编程 :核心思想和使用场景 日志 性能 权限 事务
- 完成第一个Spring
3.1. 第一步:导包
spring-framework-4.1.2.RELEASE
中文文档:Spring-Reference_2.5_zh_CN.chm
我们可以先导入核心包(core)与beans包
导包的时候注意,现在使用Spring,要完成最小导包,即:需要什么jar包,我们就导入哪一个jar包,这个对咱们认识框架的包是非常有帮助的。不然以后由于出现问题自己都不知道应该怎么解决。
3.2. 第二步:写配置文件
写配置文件我们需要有一个点入手(可以找文档,中英文文档都可以):
也可以直接拿我下面的代码去修改(这个东西不需要记忆)
配置文件的名称:application.xml application-context.xml applicationContext.xml beans.xml
<?xml version="1.0" encoding="UTF-8"?> |
文档位置:spring-framework-4.1.2.RELEASEdocsspring-framework-referencepdf 英文文档中可以找到: |
在classpath的根目录下创建一个applicactionContext.xml文件
如下:
现在咱们要开始写配置文件,建议大家依然把相应的提示配置好:
3.8. 第三步:完成测试代码
大家要记得,Spring是一个容器,我们需要把我们的类交给Spring去管理。 因为,我们的测试是创建一个普通的类,然后再通过Spring帮我们把这个类创建出来就算是成功了。
1 准备一个普通的Java类(MyBean)
public class MyBean { public void hello(){ System.out.println("hello spring..."); } } |
2 在配置文件中将这个Java类交给Spring管理
在applicationContext.xml中配置 |
<beans ...> <bean id="myBean" class="cn.itsource._01_hello.MyBean"></bean> </beans> |
3 写测试代码完成功能
注:测试部分大家要注意,要使用新版本的Junit测试
以后我们会使用Spring自己的注解测试
我这边测试有两个文件(可以使用) 如果有的同学生成的测试只有一个文件(一般是由于Eclipse的版本低的问题),那么可以直接将测试的jar包自己导入一下。这在个资料中我们是准备好的 |
4 测试代码
@Test public void testHelloSpring() throws Exception { /** *我们第一步是要启动框架,而启动框架则需要拿到Spring的核心对象 *咱们学习的第一个核心对象是BeanFactory : 顾名思义,这是一个创建Bean的工厂 *而Bean工厂创建对象又必需拿到配置文件中的数据 *因为:我们的第一步读取配置文件,拿到BeanFactory工厂 */
//第一步:读取资源文件 Resource resource = new ClassPathResource("applicationContext.xml"); //第二步:拿到核心对象 BeanFactory BeanFactory factory = new XmlBeanFactory(resource); //第三步:从工厂中拿到一个Bean对象 MyBean bean = (MyBean)factory.getBean("myBean");
System.out.println(bean); } |
- BeanFactory的认识
4.1. 什么是BeanFactory
Spring是一个容器,它会根据配置为咱们创建相应的bean(对象)。
spring使用BeanFactory来实例化、配置和管理对象,但是它只是一个接口,里面有一个getBean()方法。
4.2. 使用BeanFactory(拿到Bean对象)
4.2.1. 方式一:通过id直接拿到相应的Bean对象
//通过xml中配置的id拿到对象 MyBean bean = (MyBean)factory.getBean("myBean"); System.out.println(bean); |
4.5.1. 方式二:通过id与对象的class拿到Bean对象(重点掌握第二种)
好处:不需要强转
//通过id与对象的class拿到Bean对象 MyBean bean = factory.getBean("myBean",MyBean.class); System.out.println(bean); |
4.8.1. 方式三:通过class拿到Bean对象
限制:这个class类在配置中只能出现一次
//通过的class拿到Bean对象 MyBean bean = factory.getBean(MyBean.class); System.out.println(bean); |
如果是以下情况,方式三会出错,而方式一与方式二不会出错。
思考一下,为什么会这样?
方式一:根据id拿,可以确定 方式二:也是根据id拿,可以确定(不需要强转) 方式三:根据类型,现在有两个类型相等,无法确定(报错) |
4.16. 总结
- BeanFactory是Spring的一个核心接口 工厂对象
- BeanFactory的主要作用是拿到实例化,配置与管理Bean对象
- BeanFactory拿Spring有三种方式(id,类型,id与类型)
- 扩展BeanFactory的常用方法(看下图)
- ApplicationContext
5.1. 什么是ApplicationContext
ApplicationContext的中文意思是“应用前后关系”,它继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持、资源访问(如URL和文件)、事件传播等方面进行了良好的支持,被推荐为Java EE应用之首选,可应用在Java APP与Java Web中。
下面是ApplicationContext比BeanFactory的优势所在:
应用上下文ApplicationContext是建立在BeanFactory基础上的一种更高层次的Spring IoC容器,其除了具有普通BeanFactory的全部功能以外,还加入了以下功能: 提供了文本信息解析工具,包括I18N的支持 提供了载入文件资源的通用方法 提供了发送事件的功能 |
要使用ApplicationContext的功能,必需要导入相应的jar包:
spring-context-4.1.2.RELEASE.jar 与 spring-expression-4.1.2.RELEASE.jar
5.6. ApplicationContext的使用
5.6.1. 使用方式
接下来,我们使用一个ApplicationContext来完成拿到Bean的功能:
//拿到核心对象 ApplicationContext //注:后面的对象是从 classpath根路径开始的 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); MyBean bean = (MyBean) context.getBean("myBean"); |
5.10.1. 与BeanFactory的区别(面试题)
面试题:ApplicationContext与BeanFactory的区别
解释:都是接口,ApplicationContext是BeanFactory的子接口,拥有更多的功能与方法
重点:ApplicationContext是在启动容器创建上下文环境的时候就创建Bean对象(预先加载,迫切加载),而BeanFactory是在使用的时候才进行对象的创建(懒加载)
扩展:我们在使用ApplicationContext的时候,可以通过配置让它也变成与BeanFactory一样的懒加载:
配置一:让所有Bean都变成懒加载
<beans xmlns="http://www.springframework.org/schema/beans" .... default-lazy-init="true"> <bean id="myBean" class="cn.itsource._01_hello.MyBean"></bean> </beans> |
配置二:让其中一个Bean变成懒加载
<bean id="myBean" class="cn.itsource._01_hello.MyBean" lazy-init="true"></bean> |
5.17. 总结
- ApplicationContext是继承自BeanFactory
- ApplicationContext比BeanFactory实现了更多的功能(国际化,事件传播...)
- ApplicationContext与BeanFactory的区别
功能更强大,加载bean对象实例的时机不一样,BeanFactory是懒加载/延时加载,而ApplicationContext是迫切加载。在实际开发中我们一般会选择applicationContext.
- Spring的测试
6.1. Spring的测试的认识
6.1.1. 什么是Spring测试
咱们讲的Spring测试主要是讲SpringJunit,这个Spring自己专门写的一套测试框架功能。 (注:Spring的测试与是基于junit测试的,如下图)
传统Spring测试 |
使用Spring框架测试(由Spring来接管测试功能) |
6.5.1. Spring测试的作用
我们要思考一下,Spring为什么要自己搞一套测试框架呢?
因为三大框架整合(SSH hibernate SSM Mybatis)的时候如果Spring的配置文件不能读取,那么整个项目是跑不起来的,而Spring的测试可以让我们在不启动服务器(Tomcat)的情况下,就把相应的项目跑起来。
可以在不启动服务器的情况下,自动读取相应的配置文件。
6.6. 完成Spring测试功能
6.6.1. 第一步:导入相应的包
第一步:导入测试包(Spring为我们测试而提供的辅助代码)和AOP包
spring-aop-4.1.2.RELEASE.jar
注意,测试的兼容问题,必需使用新版本的测试包,上面测试代码部分有介绍
案例代码: |
/** * @RunWith:代表你现在使用哪一个Junit环境来测试,如果不写的话表示就是当前的Junit 配置了值后表示指定了Spring的测试环境来进行测试 * @author zhao */ @RunWith(SpringJUnit4ClassRunner.class) |
注:启动时会报错,这是由于测试包需要AOP的功能 于是这里需要导入aop的支持包 -> spring-aop-4.1.2.RELEASE.jar |
6.16.1. 测试完整代码与解释
6.18. 测试总结
- Spring单独写一套测试,可以在不启动服务器(tomcat)的情况下读取相应的配置文件,启动框架。
- 使用Spring测试需要导入Junit包,Spring的测试和Spring的aop包
@RunWith
@ContextConfiguration
@AutoWired
- 注意Spring测试中读取配置文件路径
- Spring中的Bean
7.1. 配置Bean中id与name的区别(了解)
在XML中我们可以配置id与name, 但是现在外面几乎都是使用id,name用得非常少。可能只有一些非常老的项目(Struts1)在用到name
用的时候直接用id不用name
Spring3.2之前,id必需使用标准的命名方式(不能有特殊字符等:如 /login) |
从Spring3.2版本以后不区分id,和name |
建议使用id定义bean |
Struts2的写法: <bean id="loginAction" class="cn.itsource.LoginAction" scope=”prototype”></bean> <action name="login" class="loginAction" /> Struts1的写法: <bean name="/login" class="cn.itsource.LoginAction"></bean> <action name="/login" /> |
7.11. Bean 对象的作用域(单例/多例)(重要)
指的是我们配置的Bean是单例还是多例?
使用三种拿到Bean的方式测试,拿到同一个实例,并且构造器才执行一次。证明它是一个单例,至少默认是一个单例。
那些层应该是单例?dao层,service层,DataSource(连接池),SessionFactory
那些层不应该是单例,多例(获取一次就new一次)?struts2:action层
domain层,util层不由spring管理,自己管理
Bean节点有个属性scope
singleton,默认值,单例
prototype,多例 struts2的action必须配置多例:
<bean id="scopeBean" class="cn.itsource._03_scope.MyScopeBean" scope="prototype"></bean>
一般都不用
request 放到http请求作用域
session 放到http会话作用域
7.12. Bean对象的生命周期
如果用Spring容器来管理Bean,bean对象的生命周期我们不需要去管他,直接交给Spring的容器管理
生命周期:构造 -> 初始化->运行-> 销毁
配置多例的情况下,不会执行销毁
一般我们自己不会来配置这个生命周期。而这个基本上Spring自身来使用,例如在Spring操作连接池的时候,它会在DateSource销毁的时候执行。
- 三层架构
8.1. 三层构架介绍
三层架构咱们前面都已经给大家讲解过,咱们开发把整个操作分成三层:
表现层(Web,GUI,...) |
现在咱们做的jsp/servlet/Action(struts2)就是开发表现层 |
业务层(service) |
处理相应的业务,由表现层调用,现在咱们还未加上 |
持久层(dao) |
做数据的持久化(现在咱们操作数据库就是完成持久化的功能) JDBC,SpringJDBC,Hibernate,MyBatis |
8.10. Service层规范
现在咱们就需要在项目中加上业务层了,首先,咱们要来学习开发业务层的规范,不过对于dao层规范已经如此熟悉的同学们来讲,业务层的规范简直是太简单了:
业务层设计: ------------------------------------------------ dao层: dao接口(dao包.): IXxxDAO/Dao IEmployeeDAO/Dao dao实现(dao.impl包.): XxxDAOImpl EmployeeDAOImpl
service层: service的包与dao的包应该在同一层 service接口(service包.): IXxxService IEmployeeService service实现(service.impl包.): XxxServiceImpl EmployeeServiceImpl -------------------------------------------------- 一般的,一个domain对象 (包名:domain/entity实体 beans) 一个dao组件,一个service组件 action组件 (包名: action /web.action) |
8.25. 三层架构的结构与代码练习
- 注入功能
9.1. 普通类注入
模拟使用Spring 操作 Action->Service->DAO 的过程
在使用Spring的过程中,我们需要修改过去自己的写法。 以前的对象都是自己来创建,现在,所有的对象的创建都应该交给Spring来处理。
现在,我们先模拟完成过去的从Action向下调用的过程。再将它们改为现在使用Spring后的过程。 这里涉及到了咱们的一个思维的转变(即将创建交给Spring)。
准备相应的类: |
public class UserDao { public void save(){ System.out.println("保存用户...."); } } |
public class UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; }
public void save(){ userDao.save(); } } |
public class UserAction { private UserService userService; public void setUserService(UserService userService) { this.userService = userService; } public void save(){ userService.save(); } } |
准备好配置文件 |
<bean id="userDao" class="cn.itsource._04_ioc.UserDao"></bean> <bean id="userService" class="cn.itsource._04_ioc.UserService"> <!-- 这里就是完成 类对象的属性注入 name -> 类中的属性名称(setName) ref -> 引用的哪一个Bean的id --> <property name="userDao" ref="userDao"></property> </bean> <bean id="userAction" class="cn.itsource._04_ioc.UserAction"> <property name="userService" ref="userService"></property> </bean> |
准备测试代码 |
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class IOCTest { @Autowired UserAction userAction; @Test public void testBegin() throws Exception { userAction.save(); } } |
9.54. 普通Java属性注入
加载Jdbc.properties
先复习一个DataSource(连接池)
我们创建DataSource的时候,需要给它用户名,密码,驱动,url
咱们现在使用Spring来集成一个之前学习的DBCP连接池
第一步:导入DataSource的包
在操作前:先导入相应的dbcp的jar包,而且操作数据库,也需要驱动包:
第二步:创建BasicDataSource
在学习DBCP的时候,咱们有一个核心的对象。就是BasicDataSource,咱们必需要创建好这个对象,才可以继续开始咱们的代码。
而现在,咱们需要把BasicDataSource的对象交给咱们的Spring来创建。
代码如下:
<!-- 配置一个DBCP的Bean --> <bean name="dateSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 注意:这里我们不是使用的ref引用,而是直接写的value,因此注入的数据是一个变通的值 --> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql:///test" /> <property name="username" value="root" /> <property name="password" value="admin" /> </bean> |
现在:根据咱们的习惯将重要参数放到properties中去。
导入新的命名空间,否则无法读取外部的文件 |
准备好相应的properties文件 |
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/user jdbc.username=root jdbc.password=root |
配置代码(全): |
代码测试: |
注意事项,一定要加前缀(jdbc.username),不然会出现问题。因为username已经被Spring在使用,会导致咱们的username失效,产生错误!
不加前缀报错: |
解决方案 |
<context:property-placeholder location="classpath:jdbc.properties" system-properties-mode="NEVER" /> |
- 课程总结
10.1. 重点
- Spring的作用(DI IOC AOP)
- Spring怎么配置一个Bean
- 三层架构
- Spring中的注入功能
10.2. 难点
- 理解Spring的作用
- 使用Spring配置datasource
10.3. 如何掌握?
- 三层架构要多写几次,掌握熟练 在配置文件中熟练准确的进行配置
- 三层架构完成后再使用Spring来完成三层架构的注入
- 回顾datasource是什么(根据理解来完成datasource的配置)
10.4. 排错技巧(技巧)
- 框架找错一般从下向上看(struts2,spring)
盯准:错误信息 异常 全屏 从左到右 上到下 caused by
- Spring的测试注意路径问题(是否找到核心配置文件) classpath:配置文件名称
- 课后练习
- 三层练习(熟练为止)
- Spring配置三层(熟练为止)
- 配置拿到datasource
- 面试题
- 什么是Spring
- 怎么理解DI与IOC(是什么意思)
- BeanFactory与ApplicationContext的区别
- 三层架构是哪三层? 每一层是做什么的? 为什么要使用三层架构?