一句话来说,Spring就是为了简化Web开发而存在的。
这几天为了学Spring找了不少Spring的教程,不管是不是入门的,上来都是在讲Spring的基础理念:依赖注入,应用切面,模板代码等。
说实在这些东西一上来有些不好理解,但实际上多看看,就算Java没写过什么程序,但是这些问题已经出现在了之前的JSP学习中,只是还没有清醒的意识到而已。
话不多说,不管什么教程,开始学才是最重要的,目前就采用Udemy上的一个Spring & Hibernate for Beginners (includes Spring Boot)课程以及经典的Spring in Action 4的中文版开始搞了。
import javax.servlet.http.HttpServlet;
public class Service extends HttpServlet {
private Dao dao = new Dao();
public User getUser() {
return dao.getUser();
}
}
这样的一大弊端就是Service类在自己的内部创建了一个Dao层的实例引用,使自己与具体的某个Dao层紧密绑定,如果再让这个查询用户的方法到另外一个Dao层里去做查询,那么就需要修改代码。如果很多代码都这么写死了,那么在更换DAO层的时候,工作量就非常恐怖。
Spring的一大好处就是使用了依赖注入的方法,在上边的代码中,Service类依赖Dao类进行工作,即一定要让Service知道Dao的存在,所以设置了一个类变量。
而在依赖注入中,Service类并不需要知道它自己依赖Dao类(即无需写private Dao dao = new Dao(); 当然下边的方法也没有必要写),知道依赖关系的不是Service类,而是我们程序员操作的Spring框架。
Spring框架通过一个容器,将Service和Dao都加载为一个组件(Bean),然后按照我们告诉Spring这些类之间的依赖关系,将其组装起来。
Spring In Action 4的第一章的例子就非常好的说明了这一方法的优点,而且如果是按照实现的接口注入,那么实际上两个类并不会与具体的特定实现发生耦合,这样就极大的实现了灵活性,可以在对象本身不知道的情况下,用任何不同的具体实现进行替换。
Spring的配置可以分为Java配置和XML配置,框架对于每一种配置都提供了上下文加载器,加载以后从中得到Spring容器的引用,此时需要使用一个具体的组件的对象,就无需直接实例化使用,而是通过容器的引用获得装配后的Bean对象来使用。
这个概念相比上边理解就容易多了,在之前JDBC上只要一写数据库操作,肯定那几个步骤,就算用上了DBUtils等第三方库,一样需要先获取池子并且进行配置,获取连接.....等一串都背出来的代码依然要重复写很多遍。让我想起一个现在很多年轻人估计不知道的名词:样板戏。
所以在学JDBC的时候,封装是免不了的,弄一个函数专门应对某一个具体查询就行了,然而问题还是在于,如果需求变了怎么办,全部都改吗?
Spring提供了一套模板用于迅速的操作数据库,而且无需迎合JDBC的逻辑,而是集中于编写自己的业务逻辑代码。
Spring in Action 4 第一章的模板理论好懂,但是还没有具体学,模板代码里一层又一层的匿名对象看着也比较搞,但是确实简单了不少,而且逻辑还是能够看懂的。
Spring IOC(Inversion of Control)容器
上边也提到了,在使用了Spring之后,就不是简单的直接使用自己编写的类了,一切都变成了面向Spring容器进行操作。
Spring容器就是Spring的核心,有两种Spring容器,第一种是基于Bean工厂,提供基本的DI服务。第二种是应用上下文(context)容器,提供框架级别的服务。
Spring in action 原书里简单说了Bean工厂对于大部分应用太低级了,就略过了这个内容,仅采用应用上下文容器。这里简单的说一下今天刚看到的原因:
工厂模式还是停留在直接使用原始代码的方式上的,如果Bean发生较大的改变,工厂内容也需要改变,而Spring的应用上下文容器采用反射方式,实现控制倒转,即使Bean发生变化也可以动态的响应变化。
Spring提供了针对不同配置类的应用上下文对象,就是从不同的配置文件生成不同的具体容器了。
传统的编程中,我们一般是new 出全部需要的对象,然后操作,操作完之后虚拟机就回收了。但在Spring中,bean的生命周期在Spring容器里完成,这一部分由于还没有具体接触代码,只能先有个大概印象了。