Spring的名字很诗意,在我过了初识编程的那个阶段,开始练习做一些小项目的时候,第一个接触到的就是Spring和Tomcat,但对于Spring的理解,一直处于IoC、DI及AOP的概念性认知,深谙学习道理的人自是不甘于只停留在这个层面,所以还是想努力掌握它,文章就先从Spring的core开始。PS:为了能让小白也看懂一些,本文内容不是从分析源码的角度出发(如果有奔着解读源码的同志,不用浪费宝贵时间),正如计算机是一层一层底层结构的抽象一样,我仅仅把我理解的Spring的核心抽象在此,给大家提供一个剖析的思路,可以帮助大家在实践Spring入门项目时,理解每一步是在干嘛。
何为Spring?
Spring是一个开源的、轻量级的、控制反转和依赖注入的设计层面的容器框架,它能够将各业务层面的代码松耦合,让复杂交错的业务开发变得更轻便。其实了解了它之后,说简单一点,Spring的作用就是两点:配置Bean,维护bean之间的关系。
Spring的几个关键词
Bean:个人感觉,在Spring里迷惑我次数最多的就是这个Bean,因为刚刚开始接触Bean的时候,并不知道它到底是什么?随着时间的推移,才明白,Java是面向对象的,所以类需要一个对象实例调用该类的属性和方法,所以Bean可以相当于各个层的任何类在Spring里的对象实例,拥有这个类的属性和方法。Spring作为一个容器框架,“容器”二字,其实就是指的Spring是Bean的容器,bean在Spring里被创建,并由Spring管理,等它被需要的时候,Spring会把Bean交出去。
IoC(Inversion of Controll) :控制反转,为什么说控制反转,其实这是Spring的核心思路,正常情况下,类想拥有一个对象时,会new一个对象出来,Spring产生后,将对象从盘根错节的互相依赖中解放出来,因为类不需要自己亲手去new对象,它需要对象的时候,Spring会给它一个现成的对象。
DI(Dependency Injection) :依赖注入,我觉得这个词的视角应该是Spring里的类,类的对象Bean都交由Spring创建并管理,用的时候依赖Spring注入Bean对象,所以称为依赖注入,依赖注入是Spring IoC实现的方式。
AOP(Aspect Oriented Programming):面向切面编程,在不改变原代码的基础上,为原代码新增功能,如事务、日志等这些功能。
Spring的框架
数据访问层:DAO层,以及DAO层的实现类
DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口,然后在Spring的配置文件中定义此接口的实现类,然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰,DAO层的数据源配置,以及有关数据库连接的参数都在Spring的配置文件中进行配置。
业务层:Service层,以及service的实现类
Service层主要负责业务模块的逻辑应用设计。同样是首先设计接口,再设计其实现的类,接着再Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理。Service层的业务实现,具体要调用到已定义的DAO层的接口,封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。
控制层:controller层
负责页面跳转,无工作流的简单请求处理器。
Spring core
从上图我们可以看出,Spring的core主要就是bean的容器,及其对各层各个组件的支持,其实这种维护和支持,都是靠bean来实现的,因为Spring可以接管web层,业务层,dao层,持久层的各个组件,并且可以配置各种bean, 并可以维护bean与bean的关系,当我们需要使用某个bean的时候,我们可以直接在Spring这个大的Map形式的bean容器里,getBean(id)获取即可。所以这个话,好像也是回归到了Spring的核心思想IoC,控制反转,反转就是将 创建bean,及维护bean之间的关系的这两个重要事项的控制权从程序反转到了Spring手里,而这一思想的具体操作就是DI注入依赖。这里不得不抒发一点个人感慨,想想历史,促成里程碑式进展的,往往是一些颠覆当前普通思想的人物或事物,Spring这种控制反转的思想,可以称之为“巨变”,也是前所未有的,这种想法的诞生注定了Spring的不平凡。
如何生成Bean?
说了半天,我们还不知道Spring是如何生成Bean的,其实用Spring官方的叫法是配置,Spring IoC配置Bean的方式有三种:
xml配置
Bean的信息(id, class)都配置在xml文件里,通过Spring加载文件得知去哪读取Bean的信息,然后通过反射(Class.forName().newInstance())创建Bean实例,然后通过key(id)-value(实例)的形式(申明两点:1.创建到存入Map中间有九曲十八弯,不是简单的一步到位哦,因涉及内容较多,本文先不追溯;2.不能把Spring当成一个的装Bean的Map容器,这仅仅是它功能的一小部分),存入Spring容器。
不过这种配置方法是三种里面工作量最大的,但如果引入第三方jar包时,只能选用该方法。
注解配置
具体操作时,其实是xml文件+注解的方式,xml文件会告诉Spring去找注解,然后Spring创建并管理Bean。
Java Config配置
需要一个专门的Java配置类充当xml文件的角色,它会创建好标有@Bean的Bean,交由Spring维护管理。
该方法是工作量最少的,但项目里可以依据实际情况将三种方法可以搭配使用。以上三种配置方法的代码我没有放置,因为自己实现一下可以会加深理解,所以想到的时候就动手去实践哦!
如何获取Bean?
Bean的创建和管理都依赖于Spring这个IoC容器,那我们再来看看当程序需要Bean时,是如何获取Bean的?
BeanFactory
BeanFactory是一个基本容器,指定了IoC容器的基本功能范围,配置Bean要等到使用的时候才实例化。
优点:节约内存。
缺点:速度慢。
两句关键代码如下:
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
factory.getBean("beanId");
第一行代码实例化容器,第二行代码getBean()时,才实例化Bean。
Application Context
Application Context是一种高级容器,在基础容器的水平上增加了面向框架的特性,同时应对环境做了很多配置。
配置Bean时,默认为Singleton单例模式,无论是否使用,都会加载Bean的实例。
优点:预先加载。
缺点:浪费内存。
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
如何依赖注入?
前面的内容就是讲了两点:Spring IoC容器配置Bean有三种方式,实例化Bean有两种方式,控制反转的思想再重申一下,程序把生成Bean、维护Bean之间关系的这两个控制权反转到了Spring手里,然后框架里的不同层通过之前说的三种里的任意一种方式告诉Spring在某个地方需要注入Bean,Spring就去装配Bean,然后注入到需要的地方,这种注入依赖是如何实现的呢?
构造器注入
Constructor注入能够强制要求调用者注入构造函数中的所有参数,否则在容器初始化时就会失败;但是如果要注入的对象过多,就会导致构造函数过于庞大。
setter方法注入
Setter注入,将原本庞大的构造函数,拆解为了一个小的构造函数和许多个set方法。setter注入不能保证对象一定会被注入,但是可以使用@Required注解,强制要求使用者注入对象,否则在容器初始化时就会报错。实际情况中,使用setter装配的方式更多一点。
小结
总结了一个简单的图:
Spring.png
网友评论