Spring Framework的基本认识
一. spring(春天)的简介
Spring Framework 是一个开源的Java/Java EE全功能栈(full-stack)的应用程序框架.最初由Rod Johnson和Juergen Hoeller等开发。Spring Framework提供了一个简易的开发方式,这种开发方式,将避
免那些可能致使底层代码变得繁杂混乱的大量的属性文件和帮助类,是一个轻量级的Java开发框架.
spring为了解决企业应用开发的复杂性而创建的。框架的主要优势之一
就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为
J2EE 应用程序开发提供集成的框架。
* Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以 从Spring中受益。
* Spring的核心是控制反转(IoC)和面向切面(AOP)。
* EE开发分成三层结构
* WEB层(view) -- Spring MVC
* 业务层(service) -- Bean管理:(IOC)
* 持久层(dao) -- Spring的JDBC模板.ORM模板用于整合其他的持久层框架
Spring框架,可以解决对象创建以及对象之间依赖关系的一种框架。且可以和其他框架一起使用;Spring与Struts, Spring与hibernate(起到整合(粘合)作用的一个框架)
Spring提供了一站式解决方案:
1) Spring Core spring的核心功能: IOC容器, 解决对象创建及依赖关系
2) Spring Web Spring对web模块的支持。
-→ 可以与struts整合,让struts的action创建交给spring
-→ spring mvc模式
3) Spring DAO Spring 对jdbc操作的支持 【JdbcTemplate模板工具类】
4) Spring ORM spring对orm的支持:
→ 既可以与hibernate整合,【session】
→ 也可以使用spring的对hibernate操作的封装
5)Spring AOP 切面编程
6)SpringEE spring 对javaEE其他模块的支持
1.1 spring的特点
* 方便解耦,简化开发
* Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理
* AOP编程的支持
* Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
* 声明式事务的支持
* 只需要通过配置就可以完成对事务的管理,而无需手动编程
* 方便程序的测试
* Spring对Junit4支持,可以通过注解方便的测试Spring程序
* 方便集成各种优秀框架
* Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持
* 降低JavaEE API的使用难度
* Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
二. spring两个重要概念:IOC容器和AOP概念的理解.
2.1 IOC容器:inverse of control,控制翻转,意思是将对象的创建权限反转给Spring!!我们代码中不再像原来那样使用new关键字创建对象
* 使用IOC可以解决的程序耦合性高的问题.
下面通过代码来理解IOC容器:
2.2 创建web工程,结构如下
01文件结构.png每个类的关键代码:
接口就一个相同的简单方法
public void save();
实现类的代码:
UserDao.class
public class UserDao implements IUserDao{
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("保存用户成功");
}
UserService.class
public class UserService implements IUserService{
private IUserDao userDao;
@Override
public void save() {
// TODO Auto-generated method stub
/*
* 不使用IOC容器的写法
* /
userDao = new UserDao();
userDao.save();
}
UserAction.class
public class UserAction implements IUserAction{
private IUserService userService;
@Override
public void save() {
// TODO Auto-generated method stub
/*
* 不使用IOC容器的写法
* */
userService = new UserService();
userService.save();
}
public static void main(String[] args) {
/*
* 不使用IOC容器的写法
* /
IUserAction userAction = new UserAction();
userAction.save();
}
}
运行工程,console打印输出:保存用户成功
这是传统的编码方式,每个类的成员变量到需要相应的new,创建出来,耦合性比较强.
2.2 使用IOC容器管理对象的创建.
2.2.1:在原来的工程上添加spring-core的六个jar包,并且在src目录下创建applicationContext.xml文件,jar包add to buil path;
02文件结构.png主要类添加set方法:
UserDao.class
public class UserDao implements IUserDao{
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("保存用户成功");
}
}
UserService.class
public class UserService implements IUserService{
private IUserDao userDao;
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
// TODO Auto-generated method stub
/*
* 不使用IOC容器的写法
userDao = new UserDao();
userDao.save();
*/
userDao.save();
}
}
UserAction.class
public class UserAction implements IUserAction{
private IUserService userService;
public void setUserService(IUserService userService) {
this.userService = userService;
}
@Override
public void save() {
// TODO Auto-generated method stub
/*
* 不使用IOC容器的写法
userService = new UserService();
userService.save();
*/
userService.save();
}
public static void main(String[] args) {
/*
* 不使用IOC容器的写法
IUserAction userAction = new UserAction();
userAction.save();
*/
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserAction action = (UserAction)ac.getBean("userAction");
action.save();
}
}
在applicationContext.xml文件添加bean约束和节点
applicationContext.xml
<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="userDao" class="com.it.dao.UserDao"></bean>
<bean id="userService" class="com.it.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userAction" class="com.it.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
</beans>
运行工程,console打印输出:保存用户成功.
我们发现,只需要通过在XML文件中进行配置,对象的创建就交给了spring的IOC容器.我们的代码就不再需要new 关键字进行创建,直接getBean("id")进行获取;这就是IOC的基本体现.
引出了另外一个概念:
- 依赖注入, dependency injection 处理对象的依赖关系
- 和控制反转的区别:
控制反转: 解决对象创建的问题 【对象创建交给别人】
依赖注入: 在创建完对象后, 对象的关系的处理就是依赖注入 【通过set方法依赖注入】
8.3 IOC容器获取的两种方式
8.3.1 创建User类
User.java
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(int id, String name) {
super();
this.id = id;
this.name = name;
}
public User() {
// TODO Auto-generated constructor stub
super();
this.id = 22;
this.name = "Jack";
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.id +"->"+this.name;
}
}
IOC容器获取方式一:
@Test
public void testIOC1() {
//1.把对象的创建交给IOC容器
//这种加载方式会采用懒加载,调用getBean的时候才创建
ClassPathResource resource = new ClassPathResource("applicationContext.xml");
//2.创建容器对象(Bean工厂),IOC容器=工厂类+applicationContext.xml
BeanFactory factory = new XmlBeanFactory(resource);
User user = (User) factory.getBean("user");
System.out.println(user);
}
方式二:
//2.直接得到IOC容器(方便,常用)
@Test
public void testIOC2() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) ac.getBean("user");
System.out.println(user);
}
要记得在applicationContext.xml配置user的bean节点.
8.3.2 IOC容器创建对象:
创建对象, 有几种方式:
1) 调用无参数构造器
2) 带参数构造器
3) 工厂创建对象
工厂类,静态方法创建对象
工厂类,非静态方法创建对象
测试几种创建方式:
配置applicationContext.xml,添加bean节点
<!--1. 默认无参数构造函数 -->
<bean id="user" class="com.it.entity.User"></bean>
<!-- 2.带参数构造器 -->
<bean id="user2" class="com.it.entity.User">
<constructor-arg index="0" value="33"></constructor-arg>
<constructor-arg index="1" value="Rose" type="java.lang.String"></constructor-arg>
</bean>
<!-- 3.引用参数 -->
<bean id="name" class="java.lang.String">
<constructor-arg value="Roses"></constructor-arg>
</bean>
<bean id="user3" class="com.it.entity.User">
<constructor-arg index="0" value="44"></constructor-arg>
<constructor-arg index="1" ref="name"></constructor-arg>
</bean>
<!-- 4.工厂类创建对象 -->
<!-- 先创建工程 -->
<bean id="factory" class="com.it.dependency.ObjectFacctory"></bean>
<!-- 4.1工厂类,实例方法 -->
<!-- factory实例方法创建user对象 -->
<bean id="user4" factory-bean="factory" factory-method="getInstance"></bean>
<!-- 4.2工厂类静态方法 -->
<bean id="user5" class="com.it.dependency.ObjectFacctory" factory-method="getStaticInstance"></bean>
创建对象工厂类ObjectFactory.java
package com.it.dependency;
import com.it.entity.*;
public class ObjectFacctory {
//工厂类创建对象
//实例方法创建对象
private User getInstance(){
return new User(100, "Jack");
}
//静态方法创建对象
private static User getStaticInstance(){
return new User(102, "Jack2");
}
}
测试类App.java,关键代码
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void testIOCCreateObject() {
//调用默认参数构造器
User user = (User) ac.getBean("user");
System.out.println(user);
}
@Test
public void testIOCCreateObject1() {
//带参数构造器
User user = (User) ac.getBean("user2");
System.out.println(user);
}
@Test
public void testIOCCreateObject2() {
//调用引用参数
User user = (User) ac.getBean("user3");
System.out.println(user);
}
@Test
public void testIOCCreateObject3() {
//调用工厂类实例方法
User user = (User) ac.getBean("user4");
System.out.println(user);
}
@Test
public void testIOCCreateObject4() {
//调用工厂类静态方法
User user = (User) ac.getBean("user5");
System.out.println(user);
}
8.4 Spring框架的属性注入:对象依赖关系
对于类成员变量,常用的注入方式有两种
* 构造函数注入
* 属性setter方法注入(常用)
* p名称空间
* 自动装配(了解)
* 注解(重点)
8.4.1构造函数注入
<bean id="user2" class="com.it.entity.User">
<constructor-arg index="0" value="33"></constructor-arg>
<constructor-arg index="1" value="Rose" type="java.lang.String"></constructor-arg>
</bean>
8.4.2 Set方法注入,需要注入的类要提供set方法
<!-- set方法注入值 -->
<bean id="userDao" class="com.it.dao.UserDao"></bean>
<bean id="userService" class="com.it.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userAction" class="com.it.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
8.4.3 内部bean
<!-- 内部bean赋值 -->
<bean id="userAction" class="com.it.action.UserAction" scope="prototype">
<property name="userService">
<bean id="userService" class="com.it.service.UserService">
<property name="userDao">
<bean class="com.it.dao.UserDao"></bean>
</property>
</bean>
</property>
</bean>
8.4.4 p命名空间
顶部的约束要添加,更改为
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://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">
<!--
给对象属性注入值:
# p 名称空间给对象的属性注入值
(spring3.0以上版本才支持)
-->
<bean id="userDao" class="com.it.dao.UserDao"></bean>
<bean id="userService" class="com.it.service.UserService" p:userDao-ref="userDao"></bean>
<bean id="userAction" class="com.it.action.UserAction" p:userService-ref="userService"></bean>
<!-- 传统的注入:
<bean id="user" class="cn.it.entity.User" >
<property name="name" value="xxx"></property>
</bean>
-->
<!-- p名称空间优化后 -->
<bean id="user6" class="com.it.entity.User" p:name="Jack0001"></bean>
</beans>
8.4.5 自动装配
根据名称自动装配:autowire="byName"
自动去IOC容器中找与属性名同名的引用的对象,并自动注入;
• 根据类型自动装配:autowire="byType"
必须确保改类型在IOC容器中只有一个对象;否则报错。
<bean id="userDao" class="com.it.dao.UserDao"></bean>
<bean id="userService" class="com.it.service.UserService" autowire="byName"></bean>
<!-- 根据“名称”自动装配: userAction注入的属性,会去ioc容器中自动查找与属性同名的对象 -->
<bean id="userAction" class="com.it.action.UserAction" autowire="byName"></bean>
也可以定义到全局, 这样就不用每个bean节点都去写autowire=”byName”
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://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"><!-- default-autowire="byName">
<bean id="userDao" class="com.it.dao.UserDao"></bean>
<bean id="userService" class="com.it.service.UserService"></bean>
<!-- 根据“名称”自动装配: userAction注入的属性,会去ioc容器中自动查找与属性同名的对象 -->
<bean id="userAction" class="com.it.action.UserAction"></bean>
</beans>
8.4.6 注解方式
注解方式可以简化spring的IOC容器的配置!
使用注解步骤:
1)先引入context名称空间
xmlns:context="http://www.springframework.org/schema/context"
2)开启注解扫描
<context:component-scan base-package="cn.it"></context:component-scan>
3)使用注解
通过注解的方式,把对象加入ioc容器。
创建对象以及处理对象依赖关系,相关的注解:
@Component 指定把一个对象加入IOC容器
@Repository 作用同@Component; 在持久层使用
@Service 作用同@Component; 在业务逻辑层使用
@Controller 作用同@Component; 在控制层使用
@Resource 属性注入
属性注入的注解(说明:使用注解注入的方式,可以不用提供set方法)
* 如果是注入的普通类型,可以使用value注解
* @Value -- 用于注入普通类型
* 如果注入的是对象类型,使用如下注解
* @Autowired -- 默认按类型进行自动装配
* 如果想按名称注入
* @Qualifier -- 强制使用名称注入
* @Resource -- 相当于@Autowired和@Qualifier一起使用
* 强调:Java提供的注解
* 属性使用name属性
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://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">
<context:component-scan base-package="com.it"></context:component-scan>
</beans>
UserDao.java
package com.it.dao;
import org.springframework.stereotype.Component;
import com.it.interfaces.IUserDao;
@Component(value="userDao")
public class UserDao implements IUserDao{
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("保存用户成功");
}
}
UserService.java
package com.it.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import com.it.dao.UserDao;
import com.it.interfaces.IUserDao;
import com.it.interfaces.IUserService;
@Component(value="userService")
public class UserService implements IUserService{
@Resource
private IUserDao userDao;
@Override
public void save() {
userDao.save();
}
}
UserAction.java
package com.it.action;
import javax.annotation.Resource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import com.it.interfaces.IUserAction;
import com.it.interfaces.IUserService;
import com.it.service.UserService;
@Component(value="userAction")
public class UserAction implements IUserAction{
@Resource
private IUserService userService;
@Override
public void save() {
// TODO Auto-generated method stub
userService.save();
}
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserAction action = (UserAction)ac.getBean("userAction");
action.save();
}
}
运行程序,控制台会输出: 保存用户成功
小结:
1) 使用注解,可以简化配置,且可以把对象加入IOC容器,及处理依赖关系(DI)
2) 注解可以和XML配置一起使用。
8.5 bean管理配置标签属性值
1. id属性和name属性的区别
* id -- Bean起个名字,在约束中采用ID的约束,唯一
* 取值要求:必须以字母开始,可以使用字母、数字、连字符、下划线、句话、冒号 id:不能出现特殊字符
* name -- Bean起个名字,没有采用ID的约束(了解)
* 取值要求:name:出现特殊字符.如果<bean>没有id的话 , name可以当做id使用
* Spring框架在整合Struts1的框架的时候,Struts1的框架的访问路径是以/开头的,例如:/bookAction
2. class属性 -- Bean对象的全路径
3. scope属性 -- scope属性代表Bean的作用范围
* singleton -- 单例(默认值)
* prototype -- 多例,在Spring框架整合Struts2框架的时候,Action类也需要交给Spring做管理,配置把Action类配置成多例!!
* request -- 应用在Web项目中,每次HTTP请求都会创建一个新的Bean
* session -- 应用在Web项目中,同一个HTTP Session 共享一个Bean
* globalsession -- 应用在Web项目中,多服务器间的session(集群)
4. Bean对象的创建和销毁的两个属性配置(了解)
* 说明:Spring初始化bean或销毁bean时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法
* init-method -- 当bean被载入到容器的时候调用init-method属性指定的方法
* destroy-method -- 当bean从容器中删除的时候调用destroy-method属性指定的方法
* 想查看destroy-method的效果,有如下条件
* scope= singleton有效
* web容器中会自动调用,但是main函数或测试用例需要手动调用(需要使用ClassPathXmlApplicationContext的close()方法)
8.7 集合的注入
1. 如果是数组或者List集合,注入配置文件的方式是一样的
<bean id="collectionBean" class="com.it.CollectionBean">
<property name="arrs">
<list>
<value>22</value>
<value>44</value>
</list>
</property>
</bean>
2. 如果是Set集合,注入的配置文件方式如下:
<property name="sets">
<set>
<value>哈哈</value>
<value>呵呵</value>
</set>
</property>
3. 如果是Map集合,注入的配置方式如下:
<property name="map">
<map>
<entry key="小明" value="38"/>
<entry key="小花" value="38"/>
<entry key="如花" value="29"/>
</map>
</property>
4. 如果是properties属性文件的方式,注入的配置如下:
<property name="pro">
<props>
<prop key="uname">root</prop>
<prop key="pass">123</prop>
</props>
</property>
网友评论