Spring学习1——与Spring框架的第一次接触

时间:2022-03-14 08:53:49

Spring框架是什么

第一次听说Spring框架是在接触SSH(Struts + Hibernate + Spring)时,当时只知道这一个做Java项目经常用的框架组合,而Spring就是三个框架中的一个。简单来说,Struts是MVC模式的一个具体实现;Hibernate是一个对象关系映射框架,跟数据库相关,是对JDBC的进一步封装;而Spring作为一个轻量级的控制反转(IoC)和面向切面(AoP)的容器框架,能使系统的耦合度大大降低。
Spring的核心构成:
(1)IoC: 为Inversion of Control的缩写,意为:控制反转。是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较广泛。
(2)AOP: 为Aspect Oriented Programming的缩写,意为:面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(3)容器
能管理对象的生命周期、对象与对象之间的依赖关系就是容器。

概念讲了很多,但是并不清楚Spring具体的实现形式和优势在哪儿,我们先来看个简单的例子。

一个简单的例子

这个例子用到了简单的MVC模式,我们通过对比传统的MVC模式和使用Spring之后的MVC来分析,使用Spring前后的区别。
项目结构图:


Spring学习1——与Spring框架的第一次接触

传统模式:
UserDao.java

    package springdemo1.dao;

public interface UserDao {
public void addUser(String userName,String password);
}

UserDao4MysqlImpl.java

    package springdemo1.dao;

public class UserDao4MysqlImpl implements UserDao{

@Override
public void addUser(String userName, String password) {

//打印访问Mysql的相关信息
System.out.println("UserDao4MysqlImpl.addUser");
}
}

UserDao4OracleImpl.java

    package springdemo1.dao;

public class UserDao4OracleImpl implements UserDao{

@Override
public void addUser(String userName, String password) {

//打印访问Oracle的相关信息
System.out.println("UserDao4OracleImpl.addUser");
}
}

UserManager.java

    package springdemo1.manager;

public interface UserManager {
public void addUser(String userName,String password);
}

UserManagerImpl.java

    package springdemo1.manager;

import springdemo1.dao.UserDao;
import springdemo1.dao.UserDao4OracleImpl;

public class UserManagerImpl implements UserManager{

private UserDao userDao;
//耦合度非常高,当我们需要修改数据库时就必须修改UserManagerImpl中的代码。
@Override
public void addUser(String userName, String password) {

//由我们的应用程序负责服务(对象)定位,主动发起查找
//UserDao userDao = new UserDao4MysqlImpl();
UserDao userDao = new UserDao4OracleImpl();
userDao.addUser(userName, password);
}
}

Client.java

    package springdemo1.client;

import springdemo1.manager.UserManager;
import springdemo1.manager.UserManagerImpl;

public class Client {
public static void main(String[] args){
//由我们的应用程序负责服务(对象)定位,主动发起查找
UserManager userManager = new UserManagerImpl();
userManager.addUser("jiuqiyuliang", "123456");

}
}

打印结果为:

    UserDao4OracleImpl.addUser

其类图如图所示:


Spring学习1——与Spring框架的第一次接触

由类图可以看出,在业务逻辑层的实现中,UserDao有多种不同的实现方式,例如Mysql和Oracle,UserManager的实现要依赖于UserDao的实现,此时UserManager和UserDao的实现紧密地耦合在一起了。当我们需要改变UserDao的实现时,我们必须修改在UserManager的实现UserManagerImpl中的具体代码来实现。这样来看,传统模式下,对象与对象之间发生了严重的依赖关系,耦合度十分的高而且依赖关系都写死在了代码中,项目不易修改和维护。
接下来我们使用Spring模式改造实例,实现同样的功能,让Spring管理我们的对象。
项目用到的jars:

Spring学习1——与Spring框架的第一次接触

我们需要修改的代码是Client.java和UserManagerImpl.java,并且添加applicationContext.xml文件。
Client.java

    package springdemo1.client;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import springdemo1.manager.UserManager;
import springdemo1.manager.UserManagerImpl;

public class Client {

public static void main(String[] args){
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
//到IOC容器中获取UserManager
UserManager userManager = (UserManager) factory.getBean("userManager");
//UserManager使用UserDao,在配置文件已经有依赖关系
userManager.addUser("haha", "1234");

}
}

UserManagerImpl.java

    package springdemo1.manager;

import springdemo1.dao.UserDao;
import springdemo1.dao.UserDao4OracleImpl;

public class UserManagerImpl implements UserManager{

private UserDao userDao;

//使用构造方式赋值
public UserManagerImpl(UserDao userDao) {
this.userDao = userDao;
}

@Override
public void addUser(String userName, String password) {
userDao.addUser(userName, password);
}

}

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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd"
>


<!-- 使用spring管理对象的创建,还有对象的依赖关系 -->
<bean id="userDao4Mysql" class="springdemo1.dao.UserDao4MysqlImpl"/>

<bean id="userDao4Oracle" class="springdemo1.dao.UserDao4OracleImpl"/>

<bean id="userManager" class="springdemo1.manager.UserManagerImpl">
<!-- (1)userManager使用了userDao,Ioc是自动创建相应的UserDao实现,都是由容器管理-->
<!-- (2)在UserManager中提供构造函数,让spring将UserDao实现注入(DI)过来 -->
<!-- (3)让spring管理我们对象的创建和依赖关系,必须将依赖关系配置到spring的核心配置文件中 -->

<constructor-arg ref="userDao4Oracle"/>
</bean>

</beans>

其余代码以及运行结果均和传统模式相同。
类图如图:


Spring学习1——与Spring框架的第一次接触

对比传统的实现方式,再看客户端和UserManager,我们可以发现:通过IoC或DI,我们只需要通过简单的配置,而无需任何代码就可以指定UserManager中所需的UserDao的具体实现。UserManager只需利用容器注入的UserDao实例,完成自身的业务逻辑,而不用关心具体实现来自哪、由谁实现。换句话说:我们不再需要自己负责创建对象,管理对象生命周期以及维护对象的依赖关系,这些都有Spring替我们完成了。
传统模式和Spring的对比:
传统模式:决定使用哪个具体实现由应用程序负责,在代码编译时已经确定。
Spring:调用类只依赖接口,而不依赖具体的实现类,减少了耦合。控制权交给了容器,在运行期才由容器决定将具体的实现动态的“注入”到调用类的对象中。这也是使用IoC的根本原因。

总结

现在再理解一下IoC的概念:
IoC:
通俗的来讲,以前传统模式下,由程序自己控制模块之间的关系,一切的调用都是在代码中完成,而非传统模式下,由容器来决定模块之间的关系,代码不再承担这一任务。前后程序的控制由主动变为被动,这就是控制反转的由来。
IoC的优缺点:
优点:
1.将对象的创建和依赖均定义在xml中,我们改变子类的实现变得异常简单。
2、控制反转减轻了对象之间的耦合度,减轻了对象之间的依赖关系,增加了系统的灵活性,可维护性,以及可移植性等等。
缺点:
1、生成对象的方式变复杂了,对于不熟悉这种模式的人会显得不够直观。
2、创建对象因为使用了反射技术,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。

IoC使得面向对象的世界更加简单,面向接口编程成为了可能。

参考文章

[1]【SSH进阶之路】Spring简介,搭建Spring环境——轻量级容器框架(一) http://blog.csdn.net/jiuqiyuliang/article/details/39078289