1. Spring简介

1.1 什么是Spring

spring是分层的java SE/EE应用full-stack(全栈)轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核。

 

提供了展现层SpringMVC和持久层Spring JDBCTemplate以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的java EE企业应用开源框架。

 

1.2 Spring的发展历程

1997年,IBM提出EJB的思想

1998年,SUN制定开发标准规范 EJB1.0

1999年,EJB1.1发布

2001年,EJB2.0发布

2003年,EJB2.1发布

2006年,EJB3.0发布

Rod Johnson (Spring 之父)

2017年9月发布了Spring的最新版本Spring 5.0通用版 (GA)

 

1.3 Spring的优势

1)方便解耦,简化开发

通过Spring提供的IOC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度耦合。

 

2)AOP编程的支持

通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现。

 

3)声明式事物的支持

只需要通过配置就可以完成对事物的管理,而无须手动编程。

 

4)方便程序的测试

Spring提供了对Junit4的支持,可以通过注解方便的测试Spring程序。

 

5)方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts、Hibernate、MyBatis、Quartz等)的直接支持。

 

6)降低Jave EE API的使用难度。

Spring对Java EE开发中非常难用的一些API(如JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。

 

7)java源码是金典学习范例

Spring的源码设计巧妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。

 

1.4 Spring的体系结构

Spring框架至今已集成了20多个模块,这些模块分布在以下模块中:

  • 核心容器(Core Container)

  • 数据访问/集成(Data Access/Integration)层

  • Web层

  • AOP(Aspect Oriented Programming)模块

  • 植入(Instrumentation)模块

  • 消息传输(Messaging)

  • 测试(Test)模块

Spring体系结构如下图:

 

2. Spring快速入门

2.1 Spring程序开发步骤

  1. 导入坐标

  2. 创建Bean

  3. 创建applicationContext.xml

  4. 在配置文件中进行配置Bean

  5. 创建ApplicationContext对象,通过getBean实例

 

 2.2 导入Spring开发的基本包坐标

 <properties>
        <spring.version>5.0.5.RELEASE</spring.version>
    </properties>
    <!-- 导入context坐标 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
    </dependencies>

 

2.3 编写UserDao接口和实现类

public interface UserDao {
    public void save();
}
public class UserDaoImpl implements UserDao{
    @Override
    public void save() {
        System.out.println("save running......");
    }
}

 

2.4 创建Spring核心配置文件

在resources下创建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.5 在配置文件中配置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="com.ntect.dao.userDaoImpl"></bean>
</beans>

 

 

2.6 使用Spring的API获得Bean实例

package com.ntect.demo;
import com.ntect.dao.userDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserDaoDemo {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        userDao uDao =(userDao) ctx.getBean("userDao");
        uDao.save();
    }
}

 

3. Spring配置文件

3.1 Bean标签基本配置

默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。

基本属性:

  • id: Bean实例在Spring容器中的唯一标识

  • class: Bean的全限定名称

 

3.2 Bean标签范围配置

scope指对象的作用范围 取值范围:

取值范围             说明                                                                                    

singleton

默认的,单例范围

prototype

多例的

request

Web项目中,Spring创建一个Bean对象,将对象存到request域中

session

Web项目中,Spring创建一个Bean对象,将对象存到session域中

global session

Web项目中,应用在portlet环境,如果没有portlet环境,则global Session 相当于Session

 

 

1)当scope属性取值为singleton时

Bean实例化个数:1个

Bean的实例化时机,当Spring核心配置文件被加载时,实例化配置的Bean实例(创建对象) Bean的生命周期

  • 对象创建:当加载应用,创建容器时,对象就被创建了

  • 对象运行:只要容器在,对象一直活着

  • 对象销毁:当应用卸载,销毁容器时,对象被销毁

     

2)当scope属性取值为prototype时

Bean实例化个数:多个

Bean的实例化时机,当调用getBean()方法时,实例化Bean实例(创建对象) Bean的生命周期

  • 对象创建:当使用对象时,创建新的对象实例

  • 对象运行:只要容器在,对象一直活着

  • 对象销毁:当对象长时间不用时,就被Java的垃圾回收器(GC)回收了

 

3.3 Bean生命周期配置

  • init-method:指定类中的初始化方法名称

  • destroy-method:指定类中销毁方法名称

 

3.4 Bean实例化三种方式

  • 无参构造方法实例化

  • 工厂静态方法实例化

  • 工厂实例方法实例化

 

3.4.1 无参构造方法实例化

它会根据默认的无参构造方法来创建类对象,如果bean中没有默认的无参构造函数,将会创建失败。

 <bean id="userDao" class="com.ntect.dao.userDaoImpl"></bean> 

 

3.4.2工厂静态方法实例化

使用静态工厂方法创建Bean实例时,class属性也必须指定,但此时class属性并不是指定Bean实例的实例类,而是静态工厂,Spring通过该属性知道由那个工厂来创建Bean实例。

package com.ntect.factory;

import com.ntect.dao.userDao;
import com.ntect.dao.userDaoImpl;

public class staticFactory {
    public static userDao getUserDao() {
        return new userDaoImpl();
    }
}

 

<bean id="userDao" class="com.ntect.factory.staticFactory" factory-method="getUserDao"/>

 

3.4.3 工厂实例方法实例化

实例工厂方法与静态工厂方法只有一个不同:调用静态工厂方法只需要使用工厂类即可,而调用实例工厂方法则需要工厂实例。

package com.ntect.factory;

import com.ntect.dao.userDao;
import com.ntect.dao.userDaoImpl;

public class DynamicFactory {
    public userDao getUserDao(){
        return new userDaoImpl();
    }
}

 

<bean id="factory" class="com.ntect.factory.DynamicFactory"/>
<bean id="userDao" factory-bean="factory" factory-method="getUserDao"/>

 

3.5 Bean的依赖注入分析

 

 

3.6 Bean的依赖注入概念

依赖注入(Dependency Injection):它是Spring框架核心IOC的具体实现。

在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。

IOC 解耦只是降低他们的依赖关系,但不会消除。

那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。

简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取

 

3.7 Bean的依赖注入方式

  • 构造方法

  • set方法

 

3.7.1 构造方法

创建有参构造

package com.ntect.service;

import com.ntect.dao.userDao;

public class UserServiceImpl implements userService{
    private userDao userDao;

    public UserServiceImpl(userDao userDao){
        this.userDao = userDao;
    }
    @Override
    public void save() {
        userDao.save();

    }
}

 

配置Spring容器调用有参构造方法进行注入

    <bean id="userDao" class="com.ntect.dao.userDaoImpl"></bean>

    <bean id="userService" class="com.ntect.service.UserServiceImpl">
        <constructor-arg name="userDao" ref="userDao"/>
    </bean>

 

3.7.2 set方法

      在UserServiceImpl中添加setUserDao方法

public interface userService {
    public void save();
}
package com.ntect.service;

import com.ntect.dao.userDao;

public class UserServiceImpl implements userService{
    private userDao userDao;
    public void setUserDao(userDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void save() {
        userDao.save();

    }
}

配置Spring容器调用set方法进行注入:

<bean id="userDao" class="com.ntect.dao.userDaoImpl"></bean>
<bean id="userService" class="com.ntect.service.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
</bean>

 

P命名空间注入

P命名空间的本质也是set方法注入,但是比set方法方便,主要是在配置文件中。

  首先需要引入P命名空间:

 

xmlns:p="http://www.springframework.org/schema/p"

 

  然后需要修改注入方式:

 

<bean id="userDao" class="com.ntect.dao.userDaoImpl"/>
<bean id="userService" class="com.ntect.service.UserServiceImpl" p:userDao-ref = "userDao"></bean>

 

3.8 Bean的依赖注入的数据类型

注入数据的三种数据类型:

  • 普通数据类型

  • 引用数据类型

  • 集合数据类型

 

3.8.1 普通数据类型注入

 1 package com.ntect.dao;
 2 
 3 public class userDaoImpl implements userDao{
 4     private String name;
 5     private int age;
 6     private String tel;
 7 
 8     public String getName() {
 9         return name;
10     }
11 
12     public void setName(String name) {
13         this.name = name;
14     }
15 
16     public int getAge() {
17         return age;
18     }
19 
20     public void setAge(int age) {
21         this.age = age;
22     }
23 
24     public String getTel() {
25         return tel;
26     }
27 
28     public void setTel(String tel) {
29         this.tel = tel;
30     }
31 
32     @Override
33     public String toString() {
34         return "userDaoImpl{" +
35                 "name='" + name + '\'' +
36                 ", age=" + age +
37                 ", tel='" + tel + '\'' +
38                 '}';
39     }
40 
41     public void save() {
42         System.out.println("name:"+name+"--age:"+age+"--tel:"+tel);
43         System.out.println("userDao save running......");
44     }
45 }
 <bean id="userDao" class="com.ntect.dao.userDaoImpl">
        <property name="name" value="麻子"/>
        <property name="age" value="18"/>
        <property name="tel" value="123456789120"/>
    </bean>

 

3.8.2 集合数据类型注入

 1 package com.ntect.dao;
 2 
 3 import com.ntect.model.User;
 4 
 5 import java.util.List;
 6 import java.util.Map;
 7 import java.util.Properties;
 8 
 9 public class userDaoImpl implements userDao{
10     private List<String> strList;
11     private Map<String, User> userMap;
12     private Properties properties;
13 
14     public void setStrList(List<String> strList) {
15         this.strList = strList;
16     }
17 
18     public void setUserMap(Map<String, User> userMap) {
19         this.userMap = userMap;
20     }
21 
22     public void setProperties(Properties properties) {
23         this.properties = properties;
24     }
25 
26     public void save() {
27         System.out.println("strLiist:"+strList);
28         System.out.println("userMap:"+userMap);
29         System.out.println("properties:"+properties);
30         System.out.println("userDao save running......");
31     }
32 }
 1 <bean id="userDao" class="com.ntect.dao.userDaoImpl">
 2         <property name="strList">
 3             <list>
 4                 <value>1111</value>
 5                 <value>222</value>
 6                 <value>33</value>
 7             </list>
 8         </property>
 9         <property name="userMap">
10             <map>
11                 <entry key="u1" value-ref="user1"/>
12                 <entry key="u2" value-ref="user2"/>
13             </map>
14         </property>
15         <property name="properties">
16             <props>
17                 <prop key="p1">p21</prop>
18                 <prop key="p2">p22</prop>
19                 <prop key="p3">p23</prop>
20             </props>
21         </property>
22     </bean>
23     <bean id="user1" class="com.ntect.model.User">
24         <property name="name" value="zhangsan"/>
25         <property name="address" value="chongqing"/>
26     </bean>
27     <bean id="user2" class="com.ntect.model.User">
28         <property name="name" value="lisi"/>
29         <property name="address" value="tianjin"/>
30     </bean>

 

3.9 引入其他配置文件(可用于分模块化开发)

实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载

 <import resource="applicationContext-xxx.xml"/>

 

4. Spring相关API

4.1 ApplicationContext的继承体系

img

4.2 ApplicationContext的实现类

  • ClassPathXmlApplicationContext

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

          这个实现类是从根路径下加载配置文件, 推荐使用这种, 也就是resources文件夹下

 

  • FileSystemXmlApplicationContext

ApplicationContext app = new FileSystemXmlApplicationContext("D:\\ideaWorkplace\\spring\\ntect_spring_ioc\\src\\main\\resource\\applicationContext.xml");

          这个实现类是从磁盘路径上加载, 配置文件可以放在任意的位置

  • AnnotationConfigApplicationContext

    当使用的是注解配置容器对象时, 才需要使用此类来创建spring容器

 

4.3 getBean()方法使用

 1 public class UserDaoImpl implements UserDao {
 2     List<User> userList;
 3  
 4     public List<User> getUserList() {
 5         return userList;
 6     }
 7  
 8     public void setUserList(List<User> userList) {
 9         this.userList = userList;
10     }
11 }
1 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
2         userDao uDao =(userDao) ctx.getBean("userDao");
3         userDao userDao = ctx.getBean(userDao.class);