一、什么Spring
- 1、 什么是框架
一组jar包的集合,是一个半成品,只解决某一个领域的问题 - 2、Spring的含义
-
Spring是一个轻量级的DI/IOC与AOP的容器框架
-
**轻量级:**相对于EJB(以前一个重量级框架)来讲的,框架更加简单,功能也很强大
-
DI:依赖注入(对象自己不创建,依赖于Spring容器,Spring会把对象创建并交给他)
-
IOC:控制反转(对象的控制权反转给Spring),和DI说的是一回事,是一种设计思想。
-
AOP:面向切面编程(可以在代码的任意位置加上你自己的功能)
-
容器:Spring就是一个Bean工厂(Bean就是对象)
◆目的:解决企业应用开发的复杂性
◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
◆范围:任何Java应用
-
二 、为什么要学习Spring
- 1、开发应用时遇到的问题:
-
- 代码耦合高
public class EmployeeServiceImpl {
private IEmployeeDao employeeDao = new EmployeeDaoImpl();
}
问题:若把IEmployeeDao的实现改成:HibernateDaoImpl
----->简单工厂设计模式
-
- 对象之间依赖关系处理繁琐
public class EmpployeeAction {
private IEmployeeService service;
private IDepartmentService departmentService;
}
-----------------------------------------------------------
public class EmpployeeService{
private IEmployeeDao dao;
}
//如果对象有很多,且互相存在依赖关系,并且有的对象需要单例模式,有的则需要多个实例。--->IoC
-
- 事务控制繁琐
-对于事务,可以使用Filter或是Struts2的拦截器实现,但这样有一些不好的地方:
1,此时事务开在表现层,事务周期太长。
2,有的action方法没有用到数据库操作,不需要开事务。
3,不能针对某个具体功方法配置事务是否是只读的,因为有的方法只是查询数据。
- 事务控制繁琐
解决方案:
- 把事务开启在 service 层,是极好的。但是: 每个方法前都要开启事务,每个方法后都要关闭事务。—>代码臃肿,开发效率低下。
- 如何降低业务逻辑部分之间耦合度,提高程序的可重用性,同时提高开发的效率!—>AOP
EmployeeService{
public void save(...){
开启事务
dao.save(...);
关闭事务
}
public void update(...){
开启事务
dao.update(...);
关闭事务
}
}
-
Spring框架的包分析:
spring-framework-3.x.RELEASE:Spring核心组件。
docs: Spring开发、帮助文档。
libs: Spring核心组件的。jar包、源代码、文档。
schema : Spring配置文件的schema约束文件。
spring-framework-3.x.RELEASE-dependencies:Spring依赖的第三方组件。
包含了各大开源组织提供的依赖jar。比如apache common下的:dbcp.jar pool.jar logging.jar -
Spring的优势
1.低侵入/低耦合(降低组件之间的耦合度,实现软件各层之间的解耦。)
2.声明式事务管理
3.方便集成其他框架
4.降低JavaEE开发难度
5.Spring框架中包括JavaEE 三层的每一层的解决方案 (一站式 )
-
Spring能帮我们做什么:
-
①.Spring能帮我们根据配置文件创建及组装对象之间的依赖关系。
-
②.Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制。
-
③.Spring能非常简单的帮我们管理数据库事务。
④.Spring还提供了与第三方数据访问框架(如Hibernate、JPA)无缝集成,而且自己也提供了一套JDBC访问模板,来方便数据库访问。
⑤.Spring还提供与第三方Web(如Struts、JSF)框架无缝集成,而且自己也提供了一套Spring
MVC框架,来方便web层搭建。
⑥.Spring能方便的与Java EE(如Java Mail、任务调度)整合,与更多技术整合(比如缓存框架)。三、Spring 的使用
-
1.导包
Spring中的:core(核心),beans(一切都是bean),context(上下文,国际化,邮件发送,…)
expression(表达式)
位置:spring-framework-4.1.2.RELEASE\libs依赖包:logging(日志包)
位置:spring-framework-3.2.0.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1 -
2.写一个简单的Class
-
3.写配置文件(xml)
3.1 要求写在classpath的根目录下
3.1 这个xml我们称之为核心配置文件,名称是可以随便取的,一般建议使用applicationContext.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
bean:代表你要配置一个类(对象)
id:这个bean的名称(唯一名称)
class:全限定名(它才可能根据反射创建对象)
-->
<bean id="myBean" class="cn.itsource_01_hello.MyBean"></bean>
</beans>
- 4.写代码获取bean
①.读取配置文件
Resource resource = new ClassPathResource("applicationContext.xml");
②.创建Bean工厂
BeanFactory factory = new XmlBeanFactory(resource);
③.通过Bean获取bean对象
MyBean bean = (MyBean)factory.getBean("myBean");
- .BeanFactory获取bean的三种方式
- 1 根据id获取 -> 需要强转
MyBean myBean = *(MyBean)beanFactory.getBean("myBean");
2 根据类型获取 -> 多个相同类型会报错
MyBean myBean = beanFactory.getBean(MyBean.class);
3 根据id与类型获取
MyBean myBean = beanFactory.getBean("myBean",MyBean.class);
- ApplicationContext:迫切加载方案
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyBean bean = (MyBean)context.getBean("MyBean");
-
ApplicationContext与BeanFactory的区别(面试题)
1、ApplicationContext继承自BeanFactory,但是它更加高级,功能更加强大(i18n,资源文件,…)
2、ApplicationContext默认是迫切加载,BeanFactory默认懒加载
3、ApplicationContext想懒加载 <beans … default-lazy-init=“true” -
bean的作用域
1.singleton
2.prototype
3.request
4.session
5.globalSession
-
singleton: 单例 ,在Spring IoC容器中仅存在一个Bean实例 (默认的scope)
-
prototype: 多例 ,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,相当于执行new XxxBean():不会在容器启动时创建对象
-
request: 用于web开发,将Bean放入request范围,request.setAttribute(“xxx”) , 在同一个request 获得同一个Bean
-
session: 用于web开发,将Bean 放入Session范围,在同一个Session 获得同一个Bean
-
globalSession: 一般用于Porlet应用环境 , 分布式系统存在全局session概念(单点登录),如果不是porlet环境,globalSession 等同于Session
在开发中主要使用 scope=“singleton”、 scope=“prototype”
对于MVC中的Action使用prototype类型,其他使用singleton
四.Spring的测试
用Spring包含住Junit4这个测试,让我们执行测试的时候,就已经开始运行Spring了
/**
* 如果我们在@ContextConfiguration中没有写路径
* 它会自动在当前包中找一个名称和类一样,后边加上-Context.xml的文件
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
}
如果不写路径,会在当前包自动去找当前这个 测试类-Context.xml的文件
例:SpringTest -> SpringTest-Context.xml
五.Spring配置细节
- 1.id与name的区别(早期name可以写特殊符,id不可以写,现在都可以写了,所以都用id)
2.bean对应的作用域 bean默认是单例的(不管拿多少次,拿到的是同一个) 我们可以配置成多例的 -> <bean … scope=“prototype”>
3.bean的生命周期(创建到销毁) init-method:初始化方法 destroy-method:销毁的方法(比如说配置一个连接池对象,当使用完毕后就应该销毁
六.三层架构
controller -> service -> dao
- 1 注入功能
- 首先准备相应的属性(setUserService)
Class UserController(){
private IUserService userService;
public void setUserService(IUserService userService){
this.userService = userService;
}
}
- 在配置文件中进入注入
name-> 类对应的属性 ref->引入的一个bean
<bean id="userController" class="...UserController">
<property name="userService" ref="userService" />
</bean>
七.Spring配置连接池
- 注意:必需要加classpath
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 表达式中加jdbc前缀 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>`
八、DI
- 自动装配(注解方式)
- Spring标签
- @Autowired
-
1,@Autowired标签: 1,通过autowired标签可以让spring自动的把属性需要的对象找出来,并注入到对象
-
2,autowired标签可以放在字段或者setter方法上面
-
3,@Autowired public void setter(OtherBean otherBean,OtherBean2 other2) {}
-
4,使用autowired标签可以注入一些spring内置的重要对象,比如BeanFactory,ApplicationContext;
-
5,默认情况下,@Autowired标签必须要能找到对应的对象,否则报错;通过required=false来避免这个问题:@Autowired(required=false)
-
6,第三方程序:spring3.0之前,需要手动配置@Autowired解析程序:spring就会自动的加入针对@Autowired标签的解析程序
<context:annotation-config /> -
7,@Autowired找bean的方式:
1),首先按照依赖对象的类型找;如果找到,就是用setter或者字段直接注入;
2),如果在Spring上下文中找到多个匹配的类型,再按照名字去找;如果没有匹配,报错;
3),可以通过使用@Qualifier(“otherBean”)标签来规定依赖对象按照bean的id+类型去找;
-
public class OtherBean {
}
public class OtherBean2 {
}
public class SomeBean {
@Autowired
private OtherBean other;
@Autowired(required = false)
private OtherBean2 other2;
public String toString() {
return "SomeBean [other=" + other + ", other2=" + other2 + "]";
}
}
<bean id="otherBean" class="cn.itsource.day2._2autowired_ann.OtherBean" />
<bean id="otherBean2" class="cn.itsource.day2._2autowired_ann.OtherBean2" />
<bean id="someBean" class="cn.itsource.day2._2autowired_ann.SomeBean"/>