spring框架入门学习

来源:互联网 发布:电脑ie卸载软件 编辑:程序博客网 时间:2024/05/16 04:53

1.   Spring概述

1.1. Spring是什么

Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,
因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,
由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。


J2EE三层架构体系

l  表现层(页面数据显示、页面跳转调度)jsp/servlet

l  业务层(业务处理和功能逻辑、事务控制)-serivice

l  持久层(数据存取和封装、和数据库打交道)dao


一站式

Spring提供了JavaEE各层的解决方案,表现层:Spring MVC,持久层:JdbcTemplate、ORM框架整合,业务层:IoC、AOP、事务控制。

轻量级:Spring的出现取代了EJB的臃肿、低效、繁琐复杂、脱离现实。


1.2. Spring体系架构


1.3. Spring的核心技术

IoC(Inverse of Control 反转控制): 将对象创建权利交给Spring工厂进行管理。

AOP(Aspect Oriented Programming 面向切面编程),基于动态代理功能增强。

1.4. 为什么要学习Spring



2.   Spring IOC快速入门


2.1. 什么是IOC

Inverse of Control,控制反转,将对象的创建权力反转给Spring框架!!

解决问题:使用IOC可以解决的程序耦合性高的问题!!

2.2. IOC的原理

2.2.1.准备工作

创建UserDao接口及其实现类UserDaoImpl

package cn.baidu.dao;public interface UserDao {public void save();}
package cn.baidu.dao.impl;import cn.baidu.dao.UserDao;public class UserDaoImpl implements UserDao {@Overridepublic void save() {System.out.println("持久层:用户保存");}}

创建UserService接口及其实现类UserServiceImpl

package cn.baidu.service;public interface UserService {public void save();}

package cn.baidu.service.impl;import cn.baidu.dao.UserDao;import cn.baidu.dao.impl.UserDaoImpl;import cn.baidu.service.UserService;publicclass UserServiceImpl implements UserService {private UserDao userDao = new UserDaoImpl();@Overridepublic void save() {System.out.println("业务层:用户保存");userDao.save();}}

2.2.2.创建测试类测试

package cn.baidu.test;import org.junit.Test;import cn.baidu.service.UserService;import cn.baidu.service.impl.UserServiceImpl;publicclass Test1 {@Testpublic void test(){UserService userService = new UserServiceImpl();userService.save();}}

 创建另一个UserDao的实现UserDaoImpl2

package cn.baidu.dao.impl;import cn.baidu.dao.UserDao;public class UserDaoImpl2 implements UserDao{@Overridepublic void save() {System.out.println("持久层:用户保存2");}}

观察以上程序发现:UserServiceUserDao耦合性过高,如果需要换一个UserDao的实现,则需要更改源代码

2.2.3.创建工厂类解决耦合性的问题

package cn.baidu.utils; import cn.baidu.dao.UserDao;import cn.baidu.dao.impl.UserDaoImpl; public class BeanFactory {    public static UserDao getBean(){      return new UserDaoImpl();   }}


修改UserServiceImpl实现类获取UserDao的方式

public class UserServiceImpl implements UserService {//private UserDao userDao = new UserDaoImpl();//采用工厂类获取UserDao对象private UserDao userDao = BeanFactory.getBean();@Overridepublic void save() {System.out.println("业务层:用户保存");userDao.save();}}

观察发现:当需要更换UserDao的实现时,不需要更改UserServiceImpl类,但还是要更改工厂类。

2.2.4.创建配置文件彻底解决耦合性的问题

在src下创建配置文件beans.xml

<?xml version="1.0"encoding="UTF-8"?><bean id="userDao"class="cn.baidu.dao.impl.UserDaoImpl2"></bean>


修改工厂类,从配置文件读取对象

public class BeanFactory {//存放所有的对象private static final Map<String,Object>map = new HashMap<String,Object>();static{SAXReader sax = new SAXReader();try {Document document = sax.read(BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml"));Element root = document.getRootElement();//获取id属性的值String id = root.attributeValue("id");//获取class属性的值String value = root.attributeValue("class");//根据class属性的值实例化对象Object obj = Class.forName(value).newInstance();//把对象存放到Map中map.put(id, obj);} catch (Exception e) {e.printStackTrace();}}/** * 根据id获取对象 * @param id * @return */public static Object getBean(String id){return map.get(id);}}


修改UserServiceImpl类

public class UserServiceImpl implements UserService {//private UserDao userDao = new UserDaoImpl();//采用工厂类获取UserDao对象//private UserDao userDao = BeanFactory.getBean();//从配置文件中读取需要的对象private UserDao userDao = (UserDao) BeanFactory.getBean("userDao");@Overridepublic void save() {System.out.println("业务层:用户保存");userDao.save();}}


观察发现:当需要更改UserDao时,只需要更改配置文件就行,不用更改源代码,程序彻底解耦了!!!


2.3. Spring开发包

官网地址:https://spring.io/

下载网址:http://repo.spring.io/libs-release-local/org/springframework/spring/


本次学习采用4.2.4这个版本

开发包目录结构


开发过程中还需要其他开源技术框架依赖Jar包集(dependencies,作用是方便依赖的其他技术的jar的导入):


2.4. Spring IOC入门

2.4.1.新建Java工程spring4_day01,导入jar包

Spring核心容器需要四个jar包



同时还需要与日志相关的两个jar包,从spring-framework-3.0.2.RELEASE-dependencies中寻找



复制log4j.properties到src下:



如何在Java工程中导入jar包?

在Java工程中新建一个目录lib,把需要导入的jar包复制到lib下,右键需要导入的jar包,build path,添加到项目中

2.4.2.创建一个接口和实现类

package cn.baidu.dao;public interface UserDao {public void save();}
package cn.baidu.dao.impl;import cn.baidu.dao.UserDao;public class  UserDaoImpl implements UserDao {@Overridepublic void  save() {System.out.println("用户保存...");}}


2.3.4.创建Spring的核心配置文件

在src下新建Spring核心配置文件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"></beans>


2.4.4.配置UserDaoImpl类

<?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="userDao"class="cn.baidu.dao.impl.UserDaoImpl"></bean></beans>

2.4.5.编写测试类

public class  Test1 {@Testpublic void test1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao = (UserDao) applicationContext.getBean("userDao");userDao.save();}}
测试发现:我们可以从spring容器中获取对象。

3.   Spring中的工厂

3.1. ApplicationContext接口

使用ApplicationContext工厂的接口,使用该接口可以获取到具体的Bean对象

接口下有两个具体的实现类

*ClassPathXmlApplicationContext            --加载类路径下的Spring配置文件
 *FileSystemXmlApplicationContext            --加载本地磁盘下的Spring配置文件

public class  Test1 {@Testpublic void  test1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao = (UserDao) applicationContext.getBean("userDao");userDao.save();}@Testpublic void  test2(){ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:/spring/applicationContext.xml");UserDao userDao = (UserDao) applicationContext.getBean("userDao");userDao.save();}}

3.2. BeanFactory工厂

BeanFactory是Spring框架早期的创建Bean对象的工厂接口

/** * 早期版本的spring工厂:BeanFactory */@Testpublic void  test3(){BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));System.out.println("工厂对象创建出来了");UserDao userDao = (UserDao) factory.getBean("userDao");userDao.save();}

 BeanFactory和ApplicationContext的区别
            *BeanFactory                --BeanFactory采取延迟加载,第一次getBean时才会初始化Bean
            *ApplicationContext        -- 在加载applicationContext.xml时候就会创建具体的Bean对象的实例,还提供了一些其他的功能:
                                       * 事件传递
                                       * Bean自动装配
                                       * 各种不同应用层的Context实现


4.   Spring配置文件

4.1.  id属性

id属性是bean的唯一标识

4.2. class属性

bean的全路径名

<bean id="userDao"class="cn.baidu.dao.impl.UserDaoImpl"/>

4.3. scope属性

scope属性代表Bean的作用范围

singleton:单例(默认值)

prototype:多例,在Spring框架整合Struts2框架的时候,Action类也需要交给Spring做管理,配置把Action类配置成多例!!

request:应用在web应用中,将创建的对象存入到request域中。

session:应用在web应用中,将创建的对象存入到session域中

globalsession:应用在porlet环境下使用。将创建的对象存入到全局的session中。

<bean id="userDao"class="cn.baidu.dao.impl.UserDaoImpl"scope="prototype"/>

修改测试类:

@Testpublic void test1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");System.out.println("工厂对象创建出来了");UserDao userDao = (UserDao) applicationContext.getBean("userDao");UserDao userDao1 = (UserDao) applicationContext.getBean("userDao");userDao.save();}

测试发现:scopeprototype时,每次获取bean,都会重新实例化

4.4. init-method属性

当bean被载入到容器的时候调用init-method属性指定的方法

public class  UserDaoImpl implements UserDao {public UserDaoImpl() {System.out.println("调用了UserDaoImpl的构造方法");}public void  init(){System.out.println("调用了init方法...");}@Overridepublic void  save() {System.out.println("用户保存...");}}
<bean id="userDao"class="cn.baidu.dao.impl.UserDaoImpl"init-method="init"/>
测试结果:

4.5. destory-method属性

当bean从容器中删除的时候调用destroy-method属性指定的方法

想查看destroy-method的效果,有如下条件:

           scope= singleton有效

           web容器中会自动调用,但是main函数或测试用例需要手动调用(需要使用ClassPathXmlApplicationContext的close()方法)

@Testpublic void  test1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");System.out.println("工厂对象创建出来了");UserDao userDao = (UserDao) applicationContext.getBean("userDao");userDao.save();//要看到destroy方法执行,需要调用ClassPathXmlApplicationContext.close方法((ClassPathXmlApplicationContext)applicationContext).close();}

5.   Spring生成bean的三种方式

5.1. 无参构造方法

默认调用无参构造方法实例化bean

5.2. 静态工厂实例化方式

通过调用工厂类的静态方法来生成bean

编写DepartmentDao接口

package cn.baidu.dao;publicinterface DepartmentDao {public void  save();}

编写DepartmentDaoImpl实现类

package cn.baidu.dao.impl;import cn.baidu.dao.DepartmentDao;public class  DepartmentDaoImpl implements DepartmentDao{@Overridepublic void  save() {System.out.println("部门保存...");}}

编写工厂类

package cn.baidu.dao.impl;import cn.baidu.dao.DepartmentDao;public class  DepartmentDaoFactory {/** * 静态工厂方法获取对象 * @return */public static  DepartmentDao create(){return new  DepartmentDaoImpl();}}
编写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="userDao" class="cn.baidu.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory"/><bean id="departmentDao" class="cn.baidu.dao.impl.DepartmentDaoFactory" factory-method="create"></bean></beans>

5.3. 实例工厂实例化方式

 实例工厂代码:

package cn.baidu.dao.impl;import cn.baidu.dao.DepartmentDao;public class  DepartmentDaoFactory {/** * 静态工厂方法获取对象 * @return */public static  DepartmentDao create(){return new  DepartmentDaoImpl();}/** * 实例工厂方法获取对象 * @return */public DepartmentDao create1(){return new  DepartmentDaoImpl();}}

编写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="userDao" class="cn.baidu.dao.impl.UserDaoImpl" init-method="init "destroy-method="destory"/><!--  <bean id="departmentDao" class="cn.baidu.dao.impl.DepartmentDaoFactory" factory-method="create"></bean> --><bean id="departmentDaoFactory" class="cn.baidu.dao.impl.DepartmentDaoFactory"></bean><bean id="departmentDao" factory-bean="departmentDaoFactory" factory-method="create1"></bean></beans>

6.   依赖注入

6.1. 什么是依赖注入

IOC和DI的概念:
        *IOC        -- Inverse of Control,控制反转,将对象的创建权反转给Spring!!
        *DI        -- Dependency Injection,依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中!!

如果UserServiceImpl的实现类中有一个属性,那么使用Spring框架的IOC功能时,可以通过依赖注入把该属性的值传入进来!!

6.2. 构造方法注入

 Car实体类

package cn.baidu.domain;public class  Carimplements Serializable{privatestaticfinallongserialVersionUID = 1L;private String name;private Double price;public Car(String name, Double price) {this.name = name;this.price = price;}public String getName() {returnname;}public void  setName(String name) {this.name = name;}public Double getPrice() {returnprice;}public void  setPrice(Double price) {this.price = price;}@Overridepublic String toString() {return"Car [name=" + name + ", price=" + price + "]";}}

配置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="userDao" class="cn.baidu.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory"/><!--  <bean id="departmentDao" class="cn.baidu.dao.impl.DepartmentDaoFactory" factory-method="create"></bean> --><bean id="departmentDaoFactory" class="cn.baidu.dao.impl.DepartmentDaoFactory"></bean><bean id="departmentDao" factory-bean="departmentDaoFactory" factory-method="create1"></bean><!-- 构造方法注入 --><bean id="car" class="cn.baidu.domain.Car"><constructor-arg name="name" value="奥迪A6"></constructor-arg><constructor-arg name="price" value="57.3"></constructor-arg></bean></beans>

运行结果:


6.3. set方法注入

Student实体类

public class  Student implements Serializable {privatestaticfinallongserialVersionUID = 1L;private Long id;private String name;public Long getId() {returnid;}public void  setId(Long id) {this.id = id;}public String getName() {returnname;}public void  setName(String name) {this.name = name;}@Overridepublic String toString() {return"Student [id=" + id + ", name=" + name + "]";}}

 配置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="userDao" class="cn.baidu.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory"/><!--  <bean id="departmentDao" class="cn.baidu.dao.impl.DepartmentDaoFactory" factory-method="create"></bean> --><bean id="departmentDaoFactory" class="cn.baidu.dao.impl.DepartmentDaoFactory"></bean><bean id="departmentDao" factory-bean="departmentDaoFactory" factory-method="create1"></bean><!-- 构造方法注入 --><bean id="car" class="cn.baidu.domain.Car"><constructor-arg name="name" value="奥迪A6"></constructor-arg><constructor-arg name="price" value="57.3"></constructor-arg></bean><!-- set方法注入 --><bean id="student" class="cn.baidu.domain.Student"><property name="id" value="11"></property><property name="name" value="张三"></property></bean></beans>

测试结果:


注意:采用set方法注入时,类中一定要有无参构造方法,因为spring会先调用无参构造方法实例化对象。

6.4. set方法注入对象

People实体类

public class  People implements Serializable {privatestaticfinallongserialVersionUID = 1L;private Long id;private String name;private Car car;public Long getId() {returnid;}public void  setId(Long id) {this.id = id;}public String getName() {returnname;}public void  setName(String name) {this.name = name;}public Car getCar() {returncar;}public void  setCar(Car car) {this.car = car;}@Overridepublic String toString() {return"People [id=" + id + ", name=" + name + ", car=" + car + "]";}}

 配置applicationContext.xml

<!-- set方法注入对象 --><bean id="people" class="cn.baidu.domain.People"><property name="name" value="小明"></property><property name="car" ref="car"></property></bean>
运行结果:


6.5. set方法其它注入写法

通过set方法注入还有其它两种写法:

6.5.1.p命名空间的写法

新建Car1类

package cn.baidu.domain;public class  Car1 {private String name;private double price;public void  setName(String name) {this.name = name;}public void  setPrice(doubleprice) {this.price = price;}@Overridepublic String toString() {return"Car1 [name=" + name + ", price=" + price + "]";}}

在applicationContext.xml中引入p命名空间


采用p:属性名的形式注入值(spring2.5提供的)

<!-- p命名空间注入 --><bean id="car1" class="cn.baidu.domain.Car1" p:name="奔驰" p:price="100.2"></bean>

6.5.2.SpEL的写法(spring3.0提供)

<!-- SpEL注入 --><bean id="car1" class="cn.baidu.domain.Car1"><property name="name" value="#{'哈弗H5'}"></property><property name="price" value="#{10}"></property></bean>

注入字符串:#{‘字符串’}

注入数字:#{数字}

注入其它对象:#{对象id}

<bean id="people" class="cn.baidu.domain.People"><property name="name" value="#{'小明'}"></property><property name="car" value="#{car}"></property></bean>

还可以注入其它对象的属性或方法的返回值

public class  CarInfo {public String getCarName(){return "宝骏560";}public double calculatePrice(){return Math.random() * 10000;}}
<bean id="carInfo"class="cn.baidu.domain.CarInfo"></bean><!-- SpEL注入 --><bean id="car1" class="cn.baidu.domain.Car1"><!-- <property name="name" value="#{'哈弗H5'}"></property><property name="price" value="#{10}"></property> --><property name="name" value="#{carInfo.carName}"></property><property name="price" value="#{carInfo.calculatePrice()}"></property></bean>

注意:#{carInfo.carName}会调用getCarName方法获取汽车的名称;而#{carInfo.calculatePrice()}会直接调用calculatePrice方法获取汽车价格。

6.6. 数组或list注入

数组和list注入的写法是一样的

新建bean类

public class  CollectionBean {private String[] array;public void  setArray(String[] array) {this.array = array;}@Overridepublic String toString() {return"CollectionBean [array=" + Arrays.toString(array) + "]";}}

在applicationContext.xml中配置

<bean id="collectionBean" class="cn.baidu.domain.CollectionBean"><property name="array"><list><value>威少</value><value>哈登</value><value>莱昂纳德</value></list></property></bean>

6.7. Set集合的注入

public class  CollectionBean {private String[] array;private Set<String>set;public void  setArray(String[] array) {this.array = array;}public void  setSet(Set<String>set) {this.set = set;}@Overridepublic String toString() {System.out.println(set.getClass());return"CollectionBean [array=" + Arrays.toString(array) + ", set=" + set + "]";}}
<bean id="collectionBean" class="cn.baidu.domain.CollectionBean"><property name="array"><list><value>威少</value><value>哈登</value><value>莱昂纳德</value></list></property><property name="set"><set><value>苹果</value><value>梨子</value><value>香蕉</value></set></property></bean>

提示:spring在注入set的时,给我们注入的是一个LinkedHashSet,所以在输入set集合中的元素时,是按照我们注入的顺序来的,并不是无序的。

6.8. Map集合的注入

public class  CollectionBean {private String[] array;private Set<String>set;private Map<String,String>map;public void  setArray(String[] array) {this.array = array;}public void  setSet(Set<String>set) {this.set = set;}public void  setMap(Map<String, String>map) {this.map = map;}@Overridepublic String toString() {return"CollectionBean [array=" + Arrays.toString(array) + ", set=" + set + ", map=" + map + "]";}}
<bean id="collectionBean" class="cn.baidu.domain.CollectionBean"><property name="array"><list><value>威少</value><value>哈登</value><value>莱昂纳德</value></list></property><property name="set"><set><value>苹果</value><value>梨子</value><value>香蕉</value></set></property><property name="map"><map><entrykey="id"value="11"></entry><entrykey="name"value="张三"></entry><entrykey="age"value="20"></entry></map></property></bean>

Properties的注入

public class  CollectionBean {private String[] array;private Set<String>set;private Map<String,String>map;private Properties props;public void  setArray(String[] array) {this.array = array;}public void  setSet(Set<String>set) {this.set = set;}public void  setMap(Map<String, String>map) {this.map = map;}public void  setProps(Properties props) {this.props = props;}@Overridepublic String toString() {return"CollectionBean [array=" + Arrays.toString(array) + ", set=" + set + ", map=" + map + ", props=" + props+ "]";}}
<bean id="collectionBean" class="cn.baidu.domain.CollectionBean"><property name="array"><list><value>威少</value><value>哈登</value><value>莱昂纳德</value></list></property><property name="set"><set><value>苹果</value><value>梨子</value><value>香蕉</value></set></property><property name="map"><map><entry key="id"value="11"></entry><entry key="name"value="张三"></entry><entry key="age"value="20"></entry></map></property><property name="props"><props> <prop key="username">李四</prop><prop key="password">123</prop></props></property></bean>

6.9. 配置文件的分离

Spring配置文件的分离有两种方式:

(1)采用import标签导入另一个配置文件

Bean1类
Public class Bean1 {private String xxx;public String getXxx() {returnxxx;}Public void setXxx(String xxx) {this.xxx = xxx;}@Overridepublic String toString() {return "Bean1 [xxx=" + xxx + "]";}}

applicationContext2.xml

<?xml version="1.0"encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"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="bean1" class="cn.itcast.demo.Bean1"><property name="xxx" value="hello"></property></bean></beans>

在applicationContext.xml中引入applicationContext2.xml文件

<import resource="applicationContext2.xml"/>

(2)在实例化ApplicationContext的时候,指定多个配置文件

@Testpublic void test9(){ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");Bean1 bean1 = (Bean1) ac.getBean("bean1");System.out.println(bean1);}

原创粉丝点击