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的定义填充所有的属性。
- 调用
BeanNameAware
的setBeanName
方法。 - 调用
BeanFactoryAware
的setBeanFactory
方法。 - 调用
BeanPostProcessor
的postProcesserBeforeInitialization
方法。 - 调用
InitializingBean
的afterPropertiesSet
方法。 - 调用
<bean>
的init-method
属性指定的初始化方法。 - 调用
BeanPostProcessor
的postProcesserAfterInitialization
方法。 - 容器初始化成功,程序执行,业务逻辑调用后,下面销毁容器。
- 调用
DisposableBean
的destroy
方法。 - 调用
<bean>
的destroy-method
属性指定的销毁方法。
<bean>
有两个重要的属性init-method
和destroy-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应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
执行流程
- 用户发送请求至前端控制器DispatcherServlet;
- DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
- 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
- DispatcherServlet通过HandlerAdapter处理器适配器调用处理器;
- 执行处理器(Handler,也叫后端控制器);
- Handler执行完成返回ModelAndView;
- HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
- DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
- ViewResolver解析后返回具体View;
- DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- DispatcherServlet响应用户。
SpringMVC如何和AJAX相互调用
通过Jackson框架就可以把Java里面的对象直接转化成js可以识别的Json对象。具体步骤如下 :
- 加入
Jackson.jar
- 在配置文件中配置json的映射
- 在方法前面要加上
@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框架中都用到了哪些设计模式?
待更。。。