Spring概述

Spring框架是一个为Java应用程序的开发提供了综合、广泛的基础性支持的Java平台。Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发。Spring框架本身亦是按照设计模式精心打造,这使得我们可以在开发环境中安心的集成Spring框架,不必担心Spring是如何在后台进行工作的。

Spring框架至今已集成了20多个模块。这些模块主要被分如下图所示的核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。

使用Spring的好处有以下几点:

  • Spring是轻量的,基本的版本大约2MB。
  • Spring通过控制反转实现了松散耦合。
  • Spring支持面向切面编程,把应用业务逻辑和系统服务分开。
  • Spring包含并管理应用中对象的生命周期和配置。
  • Spring的Web框架是一个精心设计的Web MVC框架,是其它WEB框架的很好的替代品。
  • Spring提供了一个便捷的事务管理接口,适用于小型的本地事物处理(比如在单DB的环境下)和复杂的共同事物处理(比如利用JTA的复杂DB环境)。

IOC

Spring框架的核心就是IoC容器,要掌握Spring框架,就必须要理解控制反转的思想以及依赖注入的实现方式。

DI与IOC

控制反转(Inversion of Control)就是将原本在程序中手动创建对象的控制权,交由Spring框架管理,根据配置文件在运行时动态的去创建对象,并调用对象的方法。作用是实现了程序的解耦合。

依赖注入(Dependency Injection)就是将实例变量传入到一个对象中去,非自己主动初始化依赖,而是通过外部来传入依赖。比如以前可能会在构造函数中自己new一个对象赋给成员变量,依赖注入则是将已经初始化好的对象作为构造函数的一个参数传入。Spring的依赖注入有3种方式:

  • setter方法注入。
  • 构造函数注入。
  • 注解方式注入。

控制反转与依赖注入有着本质的不同:

  • 控制反转是一种思想。
  • 依赖注入是一种实现方式。

IoC容器使用依赖注入作为实现控制反转的方式,但是控制反转还有其他的实现方式,例如说ServiceLocator,所以不能将控制反转和依赖注入等同。

BeanFactory和ApplicationContext

BeanFactory是Spring框架最核心、最底层的接口,是Spring IoC容器的具体实现。BeanFactory负责读取bean配置文件实例化Bean并建立Bean之间的依赖关系,提供Bean实例缓存、生命周期管理等服务。

ApplicationContext建立在BeanFactory基础之上,称为应用上下文,提供了更多面向应用的功能。例如提供了支持国际化的文本消息、统一的资源文件读取方式和框架事件体系等,更易于创建实际应用。以下是三种较常见的ApplicationContext实现方式:

  • FileSystemXmlApplicationContext:由文件系统中的XML配置文件中读取上下文。
  • ClassPathXmlApplicationContext:由类路径的XML配置文件中读取上下文。
  • WebXmlApplicationContext:由Web应用的XML文件读取上下文。

除了以上的区别外,BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时一次性创建了所有的Bean,这样在容器启动时我们就可以发现Spring中存在的配置错误。

Spring Beans

Spring beans是那些形成Spring应用的主干java对象。它们被Spring IOC容器初始化,装配和管理。这些beans通过容器中配置的元数据创建,比如以XML文件中<bean/>的形式定义。装配Bean总共有三种方式:

  • XML配置文件。
  • 基于java的配置。
  • 基于注解的配置。

Bean的作用域

当定义一个<bean>时,我们能通过定义中的scope属性来给这个bean声明一个作用域。Spring框架支持以下五种bean的作用域:

  • singleton : bean在每个Spring Ioc 容器中只有一个实例。
  • prototype:一个bean的定义可以有多个实例。
  • request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

其中,单例bean不是线程安全的,Spring框架并没有对单例bean进行任何多线程的封装处理,关于单例bean的线程安全和并发问题需要开发者自行去搞定。

Bean的生命周期

在一个bean实例被初始化时,需要执行一系列的初始化操作以达到可用的状态。同样的,当一个bean不再被调用时需要进行相关的析构操作,并从bean容器中移除。

  • Spring容器从XML文件中读取bean的定义并实例化bean。
  • Spring根据bean的定义填充所有的属性。
  • 调用BeanNameAwaresetBeanName方法。
  • 调用BeanFactoryAwaresetBeanFactory方法。
  • 调用BeanPostProcessorpostProcesserBeforeInitialization方法。
  • 调用InitializingBeanafterPropertiesSet方法。
  • 调用<bean>init-method属性指定的初始化方法。
  • 调用BeanPostProcessorpostProcesserAfterInitialization方法。
  • 容器初始化成功,程序执行,业务逻辑调用后,下面销毁容器。
  • 调用DisposableBeandestroy方法。
  • 调用<bean>destroy-method属性指定的销毁方法。

<bean>有两个重要的属性init-methoddestroy-method用来定制初始化和注销方法,它们也有相应的注解@PostConstruct@PreDestroy

Inner Bean

当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,内部bean通常是匿名的,它们的作用域一般是prototype

Bean的自动装配

Spring引入自动装配机制就是为了解决<bean>标签下<property>标签过多导致可维护性差的问题,Spring容器能够自动装配相互合作的bean,这意味着容器不需要<constructor-arg><property>配置,能通过BeanFactory自动处理bean之间的依赖关系。在Spring框架中共有以下5种自动装配:

  • no:这是Spring框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在bean定义中用标签明确的设置依赖关系。
  • byName:该选项可以根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
  • byType:该选项可以根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到或找到多个相同类型的话就报错。
  • constructor:构造器的自动装配和byType模式类似,但是仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
  • autodetect:该模式自动探测使用构造器自动装配或者byType自动装配。首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。

AOP

面向切面编程(AOP)就是在运行时,动态地将代码切入到类的指定方法、指定位置上的一种编程思想。

通知(Advice)

就是想要的功能,也就是上说的安全、事物、日子等。你给先定义好,然后再想用的地方用一下。Spring可以应用五种类型的通知:

  • before:前置通知,在一个方法执行前被调用。
  • after:在方法执行之后调用的通知,无论方法执行是否成功。
  • after-returning:仅当方法成功完成后执行的通知。
  • after-throwing:在方法抛出异常退出时执行的通知。
  • around:在方法执行之前和之后调用的通知。

连接点(JoinPoint)

就是Spring允许是通知(Advice)的地方,基本每个方法的前、后(两者都有也行),或抛出异常时都可以是连接点,Spring只支持方法连接点。

切入点(Pointcut)

上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有十几个连接点了对吧,但是你并不想在所有方法附件都使用通知(使用叫织入,下面再说),你只是想让其中几个,在调用这几个方法之前、之后或者抛出异常时干点什么,那么就用切入点来定义这几个方法,让切入点来筛选连接点,选中那几个你想要的方法。

切面(Aspect)

切面是通知和切入点的结合。通知说明了干什么和什么时候干(什么时候通过方法名中的befor,after,around等就能知道),二切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。

织入(weaving)

把切面应用到目标对象来创建新的代理对象的过程。

引入(introduction)

允许我们在已存在的类中增加新的方法和属性。

代理(proxy)

通知目标对象后创建的对象。从客户端的角度看,代理对象和目标对象是一样的。

Spring MVC

Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一个模块。在web模型中,MVC是一种很流行的架构,通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

执行流程

  1. 用户发送请求至前端控制器DispatcherServlet;
  2. DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
  4. DispatcherServlet通过HandlerAdapter处理器适配器调用处理器;
  5. 执行处理器(Handler,也叫后端控制器);
  6. Handler执行完成返回ModelAndView;
  7. HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
  8. DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
  9. ViewResolver解析后返回具体View;
  10. DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
  11. DispatcherServlet响应用户。

SpringMVC如何和AJAX相互调用

通过Jackson框架就可以把Java里面的对象直接转化成js可以识别的Json对象。具体步骤如下 :

  1. 加入Jackson.jar
  2. 在配置文件中配置json的映射
  3. 在方法前面要加上@ResponseBody注解。

Spring注解

  • @Required:该注解表明bean的属性必须在配置的时候设置,若@Required注解的bean属性未被设置,容器将抛出BeanInitializationException。注意@Required只能设置在setter方法上。

  • @Autowired:该注解可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作,默认是按类型进行装配。在类成员变量上加上该注解时,就可以去掉相应的getter和setter方法了,Spring将直接采用Java反射机制对成员变量进行自动注入。

  • @Qualifier:当有多个相同类型的bean却只有一个需要自动装配时,将@Qualifier注解和@Autowired注解结合使用以消除这种混淆,指定需要装配的确切的bean。

  • @Resource:与@Autowired不同的是该注解默认按照名称装配,当找不到与名称匹配的bean时才会按照类型装配。注意如果没有指定name属性,并且按照默认的名称仍然找不到依赖的对象时候,会回退到按照类型装配,但一旦指定了name属性,就只能按照名称 装配了。

其它

Spring框架中都用到了哪些设计模式?

待更。。。