深入浅出 Spring
原创播客,如需转载请注明出处。原文地址:http://www.cnblogs.com/crawl/p/7683070.html
前言:笔记中提供了大量的代码示例,需要说明的是,大部分代码示例都是以图片的形式展示的,所有的图片都是来自本人所敲代码的截图,不足之处,请大家指正~
第一部分:环境搭建及 IOC 容器
一、Spring 环境在 Eclipse 中的搭建及配置
1、点击 Help --> Install New SoftWare --> Add -->Archive
2、导入 spring-tool-suite-3.6.4.RELEASE-e4.4.2-win32-x86_64.zip 压缩包 选择带有 Spring IDE 的项,进行安装即可
3、导入所需要的 jar 包
> spring 所依赖的日志 jar包 apache-commons\commons-logging-1.1.1.jar
> spring 自身的 jar包 spring-framework-4.0.0.RELEASE\libs 目录下的 4 个 jar 包,见下:
> 或者导入 (此处的 log4j 意为 log for java)
注:日志的规范:spring-framework-3.0.2.RELEASE-dependencies\org.apache.log4j\com.springsource.org.apache.log4j\1.2.15
日志的实现:spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1
补:还要把 log4j.properties 文件拷贝到类路径(src)下
二、Spring 的 IOC(Inverse of Control 控制反转):将对象创建的权利反转给 Spring 框架
1、IOC 的 Helloworld
1)创建一个接口 UserService,定义一个抽象方法 public void sayHello();
2)创建接口的实现类 UserServiceImpl,实现接口的抽象方法
public void sayHello(){ System.out.println("Hello Spring..."); }
3)创建 Spring bean 管理的配置文件: applicationContext.xml
测试:
注:Spring 在调用 ClassPathXmlApplicationContext() 方法加载applicationContext.xml 文件时,就创建相应的 bean 的实例了!
2、IOC 的核心配置文件 applicationContext.xml
bean 节点的:
id 属性:标志一个唯一的 Bean,id属性值必须唯一;必须以字母开始,可以使用字母、数字、连字符、下划线、句话、冒号 id:不能出现特殊字符
class属性: Bean 的全类名
scope属性: 代表 Bean 的作用范围 可取值:
>* singleton:单例的,默认值
>* prototype:多例的,Spring 整合 Struts2 时,Action 类交给 Spring 管理,需要配置为 prototype
> requese:WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中,和 request 周期一致
> session:WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中,和 session 周期一致
> golbalSession:WEB项目中,应用在Porlet环境.如果没有Porlet环境那么globalSession相当于session.
init-method属性:作为 Bean 初始化时执行的方法
destroy-method属性:作为 Bean 被销毁时执行的方法
三、Spring 的 依赖注入(DI:Dependency Injection):在 Spring 框架负责创建 Bean对象时,动态的将依赖对象注入到 Bean 组件中
1.两种依赖注入的方式:
注:进行依赖注入,不管是值类型的属性,还是引用类型的属性,在对应的 bean 中必须创建对应的属性,并提供 setter 方法(注解注入的情况除外)
测试: 常规调用即可
2.构造器方式注入属性
1) 注入引用类型的属性
> 构造 Car
> 配置 bean
2)注入引用类型的属性
> 创建 Person 类,添加 Car 引用
> 配置 bean
3.注入数组和集合类型的属性
1)注入 数组 和 List 集合的属性,使用 list 节点(在 property 节点中)
2)注入 Map 集合类型的属性,使用 map 节点 和 entry 节点配置
注:Set 集合的配置方式与 Map 集合类似,其使用 set 节点配置
3)注入 Properties 集合类型的属性 使用 props 和 prop 节点配置
注:需要在 类中定义以上这些集合类型的属性,再添加 setter 方法
补: Spring 的多个配置文件开发:
> 在一个配置文件中包含另一个配置文件(较常使用):
<import resource="applicationContext2.xml"></import>
> 创建工厂的时候加载多个配置文件(较少使用):
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");
四、Spring 整合 Web
1.导入 所需的 jar 包:E:\jar包开源框架-新\spring-framework-4.2.4.RELEASE\libs 目录下的 spring-web-4.2.4.RELEASE.jar
2.在 web.xml 中配置 listener 监听器,此监听器为 ServletContextListener 在 容器加载时就会创建,所以在 IOC 容器中的实例也在Web容器加载时就被创建,且只被创建一次
3.修改以前的工厂代码,改为使用 WebApplicationContext 的方式
五、IOC 注解方式
1. 搭建使用环境:
①引入所需的aop jar 包, spring-framework-4.2.4.RELEASE\libs\spring-aop-4.2.4.RELEASE.jar
②引入 context 约束:spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html 中复制即可
③开启注解的扫描
2.使用注解:
1)这里使用的是 @Component 组件
测试与常规的工厂一样
补:@Component 有三个衍生注解:
①@Controller :使用在 WEB 层
②@Service : 使用在业务层
③@Repository :使用在持久层
注:这三个注解是为了让标记类本身的用途清晰,功能目前和 @Component 一致
2)使用 @Value 注解注入基本数据类型的属性
3)注入引用类型的属性
方式一:使用 @Autowired 和 @Qualifier
方式二:使用 Java 提供的 @Resource 注解
4)使用注解设置 Bean 的作用范围
在类的上方设置 @Scope(value="prototype") 可取值:singleton 、 prototype
5)Bean的生命周期的设置(为方法添加) 了解即可
@PostConstruct 的作用相当于 init-method
@PreDestroy 的作用相当于 destroy-method
六、Spring 整合 JUnit 单元测试,方便测试
1.导入所需的 spring-test-4.2.4.RELEASE.jar jar 包 spring-framework-4.2.4.RELEASE\libs\spring-test-4.2.4.RELEASE.jar
2.为单元测试类添加注解:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
3.使用:
第二部分:Spring 的 AOP
一、AOP 概述
1. AOP:Aspect Oriented Programming 意为面向切面编程
2. AOP 采取横向抽取机制,取代了传统横向继承体系的重复性代码,主要可以实现:性能监视、事务管理、安全检查、缓存 等功能
3. 优点:可以在不修改源代码的前提下,对程序进行增强
二、AOP 的底层实现
1.基于 JDK 的动态代理:针对实现了接口的类产生代理 实例代码(代码了解即可):
> 定义 UserDAO(接口) 和 UserDaoImpl(实现类) 类,创建 save() 和 update() 两个方法
> 定义代理类:
2.Cglib 动态代理:针对没有实现接口的类产生代理. 应用的是底层的字节码增强的技术 生成当前类的子类对象.实例代码(代码了解即可):
> 定义 BookDaoImpl 类,创建 save() 和 update() 方法
> 创建代理类
三、AOP开发的相关术语
1. Joinpoint(连接点): 所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.
2. Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
3.Advice(通知/增强):指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
4.Introduction(引介):(知道即可)引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
5.Target(目标对象):代理的目标对象 如:BookDaoImpl UserDaoImpl
6.Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.也就是:生成某个类代理对象的过程
7.Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类。也就是:生成的代理对象
8.Aspect(切面): 是切入点和通知(引介)的结合。需要我们自己来编写和配置(通知需要自己来编写,切入点需要配置) 切面: 切入点 + 通知
四、AspectJ 的 XML 方式的 AOP的具体开发
1.环境配置
1)导入所需的 jar 包
* spring 框架开发的基本 jar 包
* spring 的传统AOP的开发的包
spring-aop-4.2.4.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
(spring-framework-3.0.2.RELEASE-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0)
* aspectJ 的开发包:
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
(spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE)
spring-aspects-4.2.4.RELEASE.jar
2)向 applicationContext.xml 中配置约束
2.具体使用:
准备:定义接口:CustomerDao,创建 save() 和 update() 方法
定义实现类:CustomerDaoImpl
定义测试方法:
1)创建切面类:
2)applicationContext.xml 文件中配置 AOP
补:关于 AOP 切入点的表达式:
补:关于 AOP 的通知类型
>前置通知(aop:before):在目标类的方法执行之前执行
>最终通知(aop:after):在目标类的方法执行之后执行,若程序出现异常,通知也会执行
> 后置执行(aop:after-returning):在目标类的方法正常执行后再执行
> 异常抛出通知(aop:after-throwing):在目标类抛出异常后通知
>环绕通知(aop:around):目标类方法执行前后都通知
注:特别注意 环绕通知 :
五、Spring 框架的 AOP 技术------注解的方式
1.环境准备
1)引入相关的 jar 包,见模块四
2)引入相关的约束 spring-3 的 applicationContext.xml 文件的约束已全面
3)① 定义接口:CustomerDao,创建 save() 和 update() 方法 ② 定义实现类:CustomerDaoImpl ③创建测试方法
4)编写切面类 MyAspectAnno,并在 applicationContext.xml文件中配置切面类
5)AOP 注解的入门操作:
> 在 applicationContext.xml 里配置开启 AOP 注解的自动代理
> 在切面类中设置注解
2. AOP注解的通知类型和通用切入点
1)通知类型:
* @Before :前置通知
* @AfterReturing :后置通知
* @Around :环绕通知(默认目标对象的方法不执行)
* @After :最终通知
* @AfterThrowing :异常抛出通知.
2)演示:
补:配置通用的切入点
六、Spring 的 JDBC 模板技术
1.环境的配置 -- 导入所需的 jar 包和 配置文件
还需要:
2.使用 Spring-JDBC 的模板类 JdbcTemplate
> 不使用 IOC 容器管理,手动 new 出 JdbcTemplate 对象的方式,使用的是 Spring 框架内置的数据库连接池 DriverManagerDataSource
> 使用 IOC 容器管理管理数据源
① 在 applicationContext.xml 文件中配置数据库连接池(Spring 内置)和 JdbcTemplate
②使用:
3.使用 Spring 框架管理开源的数据库连接池
1)管理 DBCP 数据库连接池
> 导入所需的 2个 jar 包,在 Spring 的依赖包中找
①spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.dbcp\1.2.2.osgi\com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
②spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.pool\1.5.3\com.springsource.org.apache.commons.pool-1.5.3.jar
> 在 applicationContext.xml 中配置 DBCP 数据库连接池
2)管理 C3P0 数据库连接池
> 导入所需的 jar 包 在 Spring 的依赖包中找
spring-framework-3.0.2.RELEASE-dependencies\com.mchange.c3p0\com.springsource.com.mchange.v2.c3p0\0.9.1.2\com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
> 在 applicationContext.xml 中配置 C3P0 数据库连接池
4、 JDBC模板类的使用--- 增 删 改 查
1) 增 删 改 操作
2)查询一条记录 使用 queryForObject() 方法
自定义实现类,先定义一个 JavaBean:Account,然后:
3)查询一组记录的 List,使用 query() 方法
七、Spring 的事务管理
1. Spring 事务管理的相关 API
1)PlatformTransactionManager 接口-----平台事务管理器(真正管理事务的类,该接口有具体的实现类(DataSourceTransactionManager 和 HibernateTransactionManager),根据不同的持久层框架,需要选择不同的实现类)
2)TransactionDefinition 接口----事务定义信息,如:事务的隔离级别、传播行为、超时信息、是否只读
补:事务的传播行为常量(常用):
* 保证同一个事务中
PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认,较常使用)
* 保证没有在同一个事务中
PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
*PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
3)TransactionStatus 接口 ------ 事务的状态
2.案例:转账环境的搭建
1)导入所需的 jar 包
IOC:6个包 AOP:4个 整合JUnit:1个 c3p0:1个 jdbc:2个 Mysql驱动:1个 导入配置文件(2个)
2)编写 AccountService、AccountDao 接口,及其实现类 AccountServiceImpl、AccountDaoImpl 详见 spring-3-tx 项目
3)JdbcDaoSupport 类:若继承该类便可通过 getJdbcTemplate() 方法获取 JdbcTemplate 对象,具体获取方法:
① 因为 JdbcDaoSupport中存在属性 JdbcTemplate,所以直接在 applicationContext.xml 文件中配置 JdbcTemplate 类,并当做属性注入到使用该类的其他类中,即可使用
②根据 JdbcDaoSupport 的源码分析,所以可以不用在 applicationContext.xml 文件中配置并注入模板类,而直接配置并注入数据库连接池即可
示例:
3.事务的管理
1)Spring的编程式事务管理(了解即可)
①配置平台事务管理器
②配置 TransactionTemplate 模板类
③在业务层注入事务的模板类 即 TransactionTemplate
④使用 TransactionTemplate 管理事务
2)Spring 的基于 AOP 的声明式事务管理
① XML 配置文件的方式(业务层的方法不需要任何修改)
> 配置平台事务管理器
> 先配置通知 注: tx:method 可以给方法设置一些数据库的属性,如:隔离级别、传播行为等 tx:method 的 name属性值可以带 * ,如 pay* 表示以 pay开头的方法
> 再配置 AOP 切面
② 使用注解的方式管理事务
> 配置平台事务管理器
> 开启事务的注解
> 在相应的 类上(表示此类中的所有方法都添加事务) 或 方法(只有此方法会添加事务)上添加 @Transactionl 注解
八、Spring 整合 SSH 三大框架
知识总结回顾:
1. Spring 整合 Struts2
1)方式一: Action 由 Struts2 创建并管理,需要依赖 struts2-spring-plugin-2.3.24.jar 这个 jar 包(不推荐使用)
① 在 struts.xml 文件中配置 Action
② 在 Action 中调用业务层的类,只要在 Spring 的配置文件中对业务层的类进行了配置,在 Action 中直接创建业务层的实例并提供 setter 方法,便可以直接调用业务层的方法。
2)方式二:Action 交由 Spring 创建并管理 (推荐使用)
① 在 Spring 的配置文件中配置 Action,必须配置成 多例的
② 重新配置 Struts.xml 配置文件中 Action 的配置,若 Action 交由 Spring 管理,其 action 节点的 class 属性为 Spring 配置文件中配置 Action 的 bean 节点的 id 属性值
③ 在 Spring 的配置文件中为 Action 注入业务层的引用属性
④ 使用:在 Action 类中定义相关业务层的引用属性,定义 setter 方法,使用即可
2.Spring 整合 Hibernate
1)方式一:带有 hibernate.cfg.xml 配置文件 (不推荐使用)
① 持久层的类需要继承 HibernateDaoSupport,此类中具有 hibernateTemplate 引用属性,分析源码可知,此类还可以通过配置 SessionFactory获取 hibernateTemplate 对象。因为持久层的类继承了 HibernateDaoSupport,即获取了其 hibernateTemplate 引用属性和 SessionFactory引用属性,所以可以直接在 Spring 配置文件中为持久化类注入 SessionFactory
② 按 Hibernate 的步骤生成 hibernate.cfg.xml 和 类名.hbm.xml 文件,并进行相应的配置,注:hibernate.cfg.xml 中不能配置绑定当前线程的操作,否则会报错!
③ 在 Spring 的配置文件中配置 LocalSessionFactoryBean,用来加载 hibernate.cfg.xml 文件和创建 SessionFactory 对象
④ 在 Spring 配置文件中配置平台事务管理器并开启事务的注解,并在相应的业务层的类或方法上添加 @Transactionl 注解
2)方式二:不带有 hibernate.cfg.xml 配置文件 (推荐使用)
思考:没有 hibernate.cfg.xml 配置文件,即把 hibernate.cfg.xml 配置文件中的内容在 Spring 的配置文件中配置,所以,在方式一的基础上:
① 在 Spring的配置文件中配置 c3p0 数据源:
② 在 LocalSessionFactoryBean 中配置 数据库连接池,方言,可选值(是否打印 SQL,是否格式化 SQL,数据表的生成策略),引入映射的配置文件
3.Hibernate 模板类--- HibernateDAOSupport 的使用
1)HibernateDAOSupport 的 getHibernateTemplate() 方法同 Hibernate 的 Session 类似,可以对数据库进行增、删、改
2)查询一条记录,HQL查询所有记录,QBC 查询所有记录,分页查询
4. SSH 框架整合延迟加载问题的解决
1)使用 HIbernateTemplate.load() 方法,默认为延迟加载
2)异常:java.lang.ClassCastException: qi.spring.ssh1.domain.Customer_$$_javassist_0 cannot be cast to javassist.util.proxy.Proxy 是由包冲突造成的,删除低版本的即可
3)懒加载异常:org.hibernate.LazyInitializationException: could not initialize proxy - no Session 是由于延迟加载时 Session 已经关闭造成的
解决:
方案一:在 Customer.hbm.xml 中的 class 节点添加 lazy="false" 属性,关闭延迟加载,不推荐使用,此方案使程序性能降低
方案二:Spring解决延迟加载的问题,在 web.xml 文件中配置一个过滤器,注:此过滤器一定要配置在 struts2 的核心过滤器之前,推荐使用此方式!!