SSM框架之Spring——Spirng简介和配置

目录

一、Spring简介

1.1Spring的优点

1.2Spring体系结构

二、Spring快速入门

2.1Spring程序开发步骤

2.2Spring快速入门

2.2.1创建Maven项目并导入Spring包

2.2.2编写Dao接口和实现类

2.2.3创建Spring核心配置文件并配置DaoImpl

2.2.4获取Bean实例

三、Spring配置文件

3.1Bean标签基本配置

3.2Bean标签范围配置

3.3Bean生命周期配置

 3.4Bean实例化的三种方式

3.5Bean的依赖注入

3.5.1Set方法实现依赖注入

3.5.2构造方法实现依赖注入

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

3.6引入其他配置文件

四、Spring相关API

4.1ApplicationContext继承体系

4.2ApplicationContext的实现类

4.3getBean()方法使用


一、Spring简介

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

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

1.1Spring的优点

Spring框架具有以下几个优势:

1、方便解耦,简化开发

通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度耦合。(简单来说就是通过IoC统一创建对象)

用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

2、支持AOP编程

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

3、支持声明式事务

可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量。

4、方便程序的测试

可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。

5、方便继承各种优秀框架

Spring对各种优秀框架(Struts、Hibernate、Mybatis、Hessian、Quartz等)的支持

6、降低JavaEE API的使用难度

Spring对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。

7、Java源码是经典学习范例

Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以及对 Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。
 

1.2Spring体系结构

Spring的体系结构可以用下图表示:

 我们在学习过程中是从下往上学习,先学底层,然后是上层应用。所以我们先要学习核心容器Core Container

二、Spring快速入门

2.1Spring程序开发步骤

传统的项目开发是先写Dao层的方法,然后在业务逻辑层Service里创建Dao对象,调用相关方法。

UserDao userDao = new UserDaoImpl();

但是Spring将对象的创建权限放在了框架内,如果想要获得对象,不用自己new,其步骤是:

  1. 实现Dao层的对象中的具体方法
  2. 在xml配置文件中把Dao对象关联到一个id标识上
  3. Spring读取xml配置文件,根据id标识获得Bean全限定名称
  4. Spring通过反射机制创建对象,然后将对象返回

 从上图可知,Spring开发的基本步骤如下:

  1. 导入Spring开发的基本包坐标
  2. 编写 Dao 接口和实现类
  3. 创建 Spring 核心配置文件
  4. 在 Spring 配置文件中配置 UserDaoImpl
  5. 使用 Spring 的 API 获得 Bean 实例

2.2Spring快速入门

2.2.1创建Maven项目并导入Spring包

我们首先创建一个Spring文件夹,用IDEA打开该文件夹,打开后右键Spring新建一个Module,

左边选择maven项目,不点击使用模板创建,直接点击next,设置好公司和项目名,

 然后后面直接点击next和finish创建好项目。现在创建的项目没有webapp,我们要进入项目设置Project Structure,设置SDK的一些参数,

 然后我们左边选择Facets项,点击+号,找到Web点击,选择spring_ioc进行添加,

 然后修改web模块的路径,

然后我们在pom.xml中导入spring框架用的jar包,

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>
</dependencies>

至此项目创建完成。

2.2.2编写Dao接口和实现类

我们创建一个Dao的接口和简单实现类,

interface UserDao {
    public void save();
}

public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("saving.........");
    }
}

2.2.3创建Spring核心配置文件并配置DaoImpl

我们在src\main\resources目录下创建一个xml文件applicationContext.xml,

 我们在xml中配置dao的实现类id,

<?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="Dao.UserDaoImpl"></bean>
</beans>

2.2.4获取Bean实例

我们新建一个Demo类,用来获取UserDao对象,

package Demo;

import Dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserDaoDemo {
    public static void main(String[] args) {
        ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");//获取ApplicationContext对象
        UserDao userDao = (UserDao) app.getBean("userDao");//获取UserDao的实例化对象
        userDao.save();
    }
}

运行结果:

三、Spring配置文件

3.1Bean标签基本配置

我们可以通过反射来获取对象,而反射是通过类的无参构造来获取对象,所以我们实现的类必须要存在无参构造。

<bean id="userDao" class="Dao.UserDaoImpl"></bean>

基本属性包括:

  • id:Bean实例在Spring容器中的唯一标识
  • class:Bean的全限定名称

3.2Bean标签范围配置

我们还可以通过scope属性配置bean对象的作用范围

取值范围 说明
singleton 默认值,单例的
prototype 多例的
request WEB项目中,Spring创建一个Bean对象,并将对象存储到request域中
session WEB项目中,Spring创建一个Bean对象,并将对象存储到session域中
global session

WEB项目中,应用在Portlet环境

如果没有Portlet环境那么globalSession相当于session

我们将scope分别设置为singleton和prototype,查看得到的两个对象地址是否相同,

public void test1(){
    ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");//获取ApplicationContext对象
    UserDao userDao1 = (UserDao) app.getBean("userDao");//获取UserDao的实例化对象
    UserDao userDao2 = (UserDao) app.getBean("userDao");//获取UserDao的实例化对象
    System.out.println(userDao1==userDao2);//查看两个对象是否为同一个地址,即是否为单例模式
}

下图左边是singleton的输出,右边是prototype的输出, 

我们可以得到以下结论:

  • 当scope的取值为singleton时:
    • Bean的实例化个数为1个
    • Bean的实例化时机为:当Spring核心配置文件加载时,就实例化了配置的Bean对象
    • Bean的生命周期:
      • 对象创建:当应用加载,创建容器时,对象就被创建了
      • 对象运行:只要容器在,对象就一直存活
      • 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
  • 当scope的取值为prototype时:
    • Bean的实例化个数为多个
    • Bean的实例化时机为:当调用getBean()方法时实例化Bean
    • Bean的生命周期:
      • 对象创建:当使用对象时,创建新的对象实例
      • 对象运行:只要对象在使用中,就一直存活
      • 对象销毁:当对象长时间不用时,被Java的垃圾回收器回收

3.3Bean生命周期配置

我们可以指定Bean对象的初始化和销毁方法,

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

我们在UserDaoImpl对象中定义初始化和销毁的方法:

public void init(){ System.out.println("UserDaoImpl对象初始化"); }
public void destory(){ System.out.println("UserDaoImpl对象销毁"); }

然后在applicationContext.xml中配置好对应关系:

<bean id="userDao" class="Dao.UserDaoImpl" init-method="init" destroy-method="destory"></bean>
public void test2(){
    ClassPathXmlApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");//获取ApplicationContext对象
    UserDao userDao = (UserDao) app.getBean("userDao");//获取UserDao的实例化对象
    app.close();//关闭容器对象,此时会执行对象中销毁的方法
}

结果如下:

 3.4Bean实例化的三种方式

  • 无参构造方法实例化:默认的方法(重要)
  • 工厂静态方法实例化
  • 工厂实例方法实例化

这里我们演示一下后面两种方法,首先我们要新建一个工厂类StaticFactory,里面定义一个静态方法获取UserDaoImpl对象,

public class StaticFactory {
    public static UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

然后我们修改一下Spring的配置文件,告诉Spring我们要走工厂静态方法实例化对象,

<bean id="userDao" class="Factory.StaticFactory" factory-method="getUserDao"></bean>

后面就和无参构造的方法一样,通过应用容器中查找id获取Bean对象。

接下来我们看看工厂实例方法如何实例化,还是新建一个工厂类DynamicFactory,定义一个非静态方法,获取UserDaoImpl对象,

public class DynamicFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

修改配置文件,

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

同样地利用id获取Bean对象。

3.5Bean的依赖注入

假设我们现在要在Service类中调用dao层的方法,我们同样要写一个UserService的接口和UserServiceImpl的实现类,在UserServiceImpl中调用dao层的方法。

package Service;

import Dao.UserDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceImpl implements UserService{
    public void save() {
        ClassPathXmlApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");//获取ApplicationContext对象
        UserDao userDao = (UserDao) app.getBean("userDao");//获取UserDao的实例化对象
        userDao.save();//调用dao层的方法
    }
}

那我们如何创建UserService类呢,我们同样可以在Spring的配置文件中给UserService类配置id。

<bean id="userDao" class="Dao.UserDaoImpl"></bean>
<bean id="userService" class="Service.UserServiceImpl"></bean>

然后同样通过id获取Bean对象,

package Demo;

import Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceDemo {
    public static void main(String[] args) {
        ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");//获取应用
        UserService userService = (UserService) app.getBean("userService");//获取UserService对象
        userService.save();//调用方法
    }
}

启动可以正常运行。但是我们发现UserServiceUserDao对象都封装到了Spring容器中。

程序调用时,首先为了获取UserSerice对象,根据id找到UserService对象,但是其中save方法中用到了UserDao对象,程序又去找Spring要UserDao对象,找到了后将UserDao对象返回给UserService进行使用。这样无疑是比较繁琐的,实现一个方法找Spring容器要了两次对象。

 所以我们希望的是在Spring容器内部,将UserDao就设导入给UserService对象(可以通过构造方法或者set方法),

这里就可以引入我们的依赖注入的概念,它是 Spring 框架核心 IOC 的具体实现。

在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。

那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

3.5.1Set方法实现依赖注入

我们先用set方法将UserDao导入给UserService对象,完成依赖注入,

package Service;
import Dao.UserDao;

public class UserServiceImpl implements UserService{
    private UserDao userDao;//定义一个私有UserDao对象

    public void setUserDao(UserDao userDao) {//通过set方法对该对象进行赋值
        this.userDao = userDao;
    }

    public void save() {
        userDao.save();//调用dao层的方法
    }
}

然后在Spring配置文件中对set方法进行配置,将UserDao设置为传入的参数(注意这里property中的name属性填的是set方法后面的字符串,并且将第一个字符改为小写,即serUserDao->userDao)

<bean id="userDao" class="Dao.UserDaoImpl"></bean>
<bean id="userService" class="Service.UserServiceImpl">
    <property name="userDao" ref="userDao"></property>
</bean>

我们还可以引入命名空间P,直接在bean标签内设置,

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

<bean id="userDao" class="Dao.UserDaoImpl"></bean>
<bean id="userService" class="Service.UserServiceImpl" p:userDao-ref="userDao"></bean>

3.5.2构造方法实现依赖注入

首先我们在UserServiceImpl类中添加一个有参构造函数,

package Service;
import Dao.UserDao;

public class UserServiceImpl implements UserService{
    private UserDao userDao;//定义一个私有UserDao对象

    public UserServiceImpl(UserDao userDao) {
        this.userDao=userDao;//通过有参构造进行赋值
    }

    public void save() {
        userDao.save();//调用dao层的方法
    }
}

同样我们对Spring配置文件进行配置,设定构造方法传入的参数值,

<bean id="userDao" class="Dao.UserDaoImpl"></bean>
<bean id="userService" class="Service.UserServiceImpl">
    <constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>

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

上述操作都是注入了引用Bean,除了对象的引用可以注入,普通数据类型、集合等都可以在容器中进行注入。主要包括:

  • 普通数据类型
  • 引用数据类型
  • 集合数据类型

接下来我们看看普通数据类型集合数据类型如何进行注入,同样地还是使用set和构造的方法。


首先看看普通数据类型,我们在UserDaoImpl中写入两个普通数据类型数据,生成set方法,并在save方法中对两个数据进行打印。

package Dao;

public class UserDaoImpl implements UserDao {
    private String username;
    private int age;

    public void setUsername(String username) {
        this.username = username;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void save() {
        System.out.println(username+"="+age);//打印用户名和年龄
        System.out.println("saving.........");
    }
}

我们在Spring配置文件中对这两个数据进行赋值,

<bean id="userDao" class="Dao.UserDaoImpl">
    <property name="username" value="tom"></property>
    <property name="age" value="18"></property>
</bean>

然后调用UserDaoImpl的save方法,输出结果为:


 然后是集合数据类型,我们在UserDaoImpl中创建几个集合数据,设置好set方法,

import Domain.User;

import java.util.List;
import java.util.Map;
import java.util.Properties;

public class UserDaoImpl implements UserDao {
    private List<String> strList;
    private Map<String, User> userMap;
    private Properties properties;

    public void setStrList(List<String> strList) {
        this.strList = strList;
    }

    public void setUserMap(Map<String, User> userMap) {
        this.userMap = userMap;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void save() {
        System.out.println(strList);
        System.out.println(userMap);
        System.out.println(properties);
        System.out.println("saving.........");
    }
}

我们同样要在Spring配置文件中对这些集合进行赋值,

<bean id="userDao" class="Dao.UserDaoImpl">
    <property name="strList">
        <list>
            <value>aaa</value>
            <value>bbb</value>
            <value>ccc</value>
        </list>
    </property>
    <property name="userMap">
        <map>
            <entry key="u1" value-ref="user1"></entry>
            <entry key="u2" value-ref="user2"></entry>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="address">wuhan</prop>
            <prop key="major">cs</prop>
        </props>
    </property>
</bean>

<bean id="user1" class="Domain.User">
    <property name="username" value="tom"></property>
    <property name="age" value="18"></property>
</bean>
<bean id="user2" class="Domain.User">
    <property name="username" value="jack"></property>
    <property name="age" value="22"></property>
</bean>

然后调用UserDaoImpl的save方法对这些集合进行打印,

3.6引入其他配置文件

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

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

我们将user的对象配置到applicationContext-user.xml中,

<bean id="user1" class="Domain.User">
    <property name="username" value="tom"></property>
    <property name="age" value="18"></property>
</bean>
<bean id="user2" class="Domain.User">
    <property name="username" value="jack"></property>
    <property name="age" value="22"></property>
</bean>

然后在主配置文件中导入,

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

这样就做到了分模块开发,主配置文件就比较精简。
 

四、Spring相关API

4.1ApplicationContext继承体系

ApplicationContext:接口类型,代表应用上下文,可以通过其实例获得 Spring 容器中的 Bean 对象

 紫色的为接口,浅绿色的为抽象类,深绿色的为实现类,所以我们一般创建实现类对象。

4.2ApplicationContext的实现类

1、ClassPathXmlApplicationContext

它是从类的根路径下(相对路径)加载配置文件(推荐使用)

ClassPathXmlApplicationContext app=new ClassPathXmlApplicationContext("XXXX.xml");
app.getBean("");//输入id标识获取Bean对象

2、FileSystemXmlApplicationContext

它是从磁盘路径上(绝对路径)加载配置文件,配置文件可以在磁盘的任意位置。

FileSystemXmlApplicationContext app=new FileSystemXmlApplicationContext("");//输入xml文件的磁盘地址即绝对路径
app.getBean("");//输入id标识获取Bean对象

3、AnnotationConfigApplicationContext

当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

4.3getBean()方法使用

getBean有两种方式获取Bean对象,一个是传入id标识,还有一种是传入字节码对象,

public Object getBean(String name) throws BeansException {
    this.assertBeanFactoryActive();
    return this.getBeanFactory().getBean(name);
}

public <T> T getBean(Class<T> requiredType) throws BeansException {
    this.assertBeanFactoryActive();
    return this.getBeanFactory().getBean(requiredType);
}

前面我们使用的都是id标识的方法,我们看看如何传入字节码对象来获取Bean对象,

public void test4(){
    ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");//获取ApplicationContext对象
    UserDao userDao = app.getBean(UserDao.class);//获取UserDao的实例化对象
    userDao.save();
}

两种方法都可以获取到Bean对象,但是两者主要有以下几点不同:

  • id标识:可以区分同类的多个对象,即可以在配置文件中创建该类的多个对象,设置不同的属性,分别指定不同标识
  • 字节码:不能区分多个对象,如果只需要类的一个对象时可以使用该方法

猜你喜欢

转载自blog.csdn.net/weixin_39478524/article/details/121252380
今日推荐