一篇文章带你了解spring框架

虽然现在流行用SpringBoot了,很多配置已经简化和封装了,但是对于Spring的一些基础我们了解一些是对我们自己的架构思想很有帮助的!接下来和笔者一起来探讨一下Spring框架吧!

1、什么是Spring框架?Spring框架有哪些主要模块?

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

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

一篇文章带你理解Spring框架
更多信息:Spring 框架教程。

2、使用Spring框架能带来哪些好处?

下面列举了一些使用Spring框架带来的主要好处:

Dependency Injection(DI) 方法使得构造器和JavaBean properties文件中的依赖关系一目了然。
与EJB容器相比较,IoC容器更加趋向于轻量级。这样一来IoC容器在有限的内存和CPU资源的情况下进行应用程序的开发和发布就变得十分有利。
Spring并没有闭门造车,Spring利用了已有的技术比如ORM框架、logging框架、J2EE、Quartz和JDK Timer,以及其他视图技术。
Spring框架是按照模块的形式来组织的。由包和类的编号就可以看出其所属的模块,开发者仅仅需要选用他们需要的模块即可。
要测试一项用Spring开发的应用程序十分简单,因为测试相关的环境代码都已经囊括在框架中了。更加简单的是,利用JavaBean形式的POJO类,可以很方便的利用依赖注入来写入测试数据。
Spring的Web框架亦是一个精心设计的Web MVC框架,为开发者们在web框架的选择上提供了一个除了主流框架比如Struts、过度设计的、不流行web框架的以外的有力选项。
Spring提供了一个便捷的事务管理接口,适用于小型的本地事物处理(比如在单DB的环境下)和复杂的共同事物处理(比如利用JTA的复杂DB环境)。
3、什么是控制反转(IOC)?什么是依赖注入?

控制反转是应用于软件工程领域中的,在运行时被装配器对象来绑定耦合对象的一种编程技巧,对象之间耦合关系在编译时通常是未知的。在传统的编程方式中,业务逻辑的流程是由应用程序中的早已被设定好关联关系的对象来决定的。在使用控制反转的情况下,业务逻辑的流程是由对象关系图来决定的,该对象关系图由装配器负责实例化,这种实现方式还可以将对象之间的关联关系的定义抽象化。而绑定的过程是通过“依赖注入”实现的。

控制反转是一种以给予应用程序中目标组件更多控制为目的设计范式,并在我们的实际工作中起到了有效的作用。

依赖注入是在编译阶段尚未知所需的功能是来自哪个的类的情况下,将其他对象所依赖的功能对象实例化的模式。这就需要一种机制用来激活相应的组件以提供特定的功能,所以依赖注入是控制反转的基础。否则如果在组件不受框架控制的情况下,框架又怎么知道要创建哪个组件?

在Java中依然注入有以下三种实现方式:

构造器注入
Setter方法注入
接口注入
4、请解释下Spring框架中的IoC?

Spring中的 org.springframework.beans 包和 org.springframework.context包构成了Spring框架IoC容器的基础。

BeanFactory 接口提供了一个先进的配置机制,使得任何类型的对象的配置成为可能。ApplicationContex接口对BeanFactory(是一个子接口)进行了扩展,在BeanFactory的基础上添加了其他功能,比如与Spring的AOP更容易集成,也提供了处理message resource的机制(用于国际化)、事件传播以及应用层的特别配置,比如针对Web应用的WebApplicationContext。

org.springframework.beans.factory.BeanFactory 是Spring IoC容器的具体实现,用来包装和管理前面提到的各种bean。BeanFactory接口是Spring IoC 容器的核心接口。

5、BeanFactory和ApplicationContext有什么区别?

BeanFactory 可以理解为含有bean集合的工厂类。BeanFactory 包含了种bean的定义,以便在接收到客户端请求时将对应的bean实例化。

BeanFactory还能在实例化对象的时生成协作类之间的关系。此举将bean自身与bean客户端的配置中解放出来。BeanFactory还包含了bean生命周期的控制,调用客户端的初始化方法(initialization methods)和销毁方法(destruction methods)。

从表面上看,application context如同bean factory一样具有bean定义、bean关联关系的设置,根据请求分发bean的功能。但application context在此基础上还提供了其他的功能。

提供了支持国际化的文本消息
统一的资源文件读取方式
已在监听器中注册的bean的事件
以下是三种较常见的 ApplicationContext 实现方式:

1、ClassPathXmlApplicationContext:从classpath的XML配置文件中读取上下文,并生成上下文定义。应用程序上下文从程序环境变量中取得。

ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);

2、FileSystemXmlApplicationContext :由文件系统中的XML配置文件读取上下文。

ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);

3、XmlWebApplicationContext:由Web应用的XML文件读取上下文。

6、Spring有几种配置方式?

将Spring配置到应用开发中有以下三种方式:

基于XML的配置
基于注解的配置
基于Java的配置
7、如何用基于XML配置的方式配置Spring?

在Spring框架中,依赖和服务需要在专门的配置文件来实现,我常用的XML格式的配置文件。这些配置文件的格式通常用<beans>开头,然后一系列的bean定义和专门的应用配置选项组成。

SpringXML配置的主要目的时候是使所有的Spring组件都可以用xml文件的形式来进行配置。这意味着不会出现其他的Spring配置类型(比如声明的方式或基于Java Class的配置方式)

Spring的XML配置方式是使用被Spring命名空间的所支持的一系列的XML标签来实现的。Spring有以下主要的命名空间:context、beans、jdbc、tx、aop、mvc和aso。

<beans>

<!-- JSON Support -->

<bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>

<bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>

</beans>
下面这个web.xml仅仅配置了DispatcherServlet,这件最简单的配置便能满足应用程序配置运行时组件的需求。

<web-app>

<display-name>Archetype Created Web Application</display-name>

<servlet>

<servlet-name>spring</servlet-name>

<servlet-class>

org.springframework.web.servlet.DispatcherServlet

</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>spring</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

</web-app>
8、如何用基于Java配置的方式配置Spring?

Spring对Java配置的支持是由@Configuration注解和@Bean注解来实现的。由@Bean注解的方法将会实例化、配置和初始化一个新对象,这个对象将由Spring的IoC容器来管理。@Bean声明所起到的作用与<bean/> 元素类似。被@Configuration所注解的类则表示这个类的主要目的是作为bean定义的资源。被@Configuration声明的类可以通过在同一个类的内部调用@bean方法来设置嵌入bean的依赖关系。

最简单的@Configuration 声明类请参考下面的代码:

@Configuration

public class AppConfig

{

@Bean

public MyService myService() {

return new MyServiceImpl();

}

}
对于上面的@Beans配置文件相同的XML配置文件如下:

<beans>

<bean id="myService" class="com.howtodoinjava.services.MyServiceImpl"/>

</beans>
上述配置方式的实例化方式如下:利用AnnotationConfigApplicationContext 类进行实例化

public static void main(String[] args) {

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

MyService myService = ctx.getBean(MyService.class);

myService.doStuff();

}
要使用组件组建扫描,仅需用@Configuration进行注解即可:

@Configuration

@ComponentScan(basePackages = "com.howtodoinjava")

public class AppConfig {

...

}
在上面的例子中,com.acme包首先会被扫到,然后再容器内查找被@Component 声明的类,找到后将这些类按照Sring bean定义进行注册。

如果你要在你的web应用开发中选用上述的配置的方式的话,需要用AnnotationConfigWebApplicationContext 类来读取配置文件,可以用来配置Spring的Servlet监听器ContrextLoaderListener或者Spring MVC的DispatcherServlet。

<web-app>

<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->

<context-param>

<param-name>contextClass</param-name>

<param-value>

org.springframework.web.context.support.AnnotationConfigWebApplicationContext

</param-value>

</context-param>

<!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified @Configuration classes. Fully-qualified packages may also be
specified for component-scanning -->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>com.howtodoinjava.AppConfig</param-value>

</context-param>

<!-- Bootstrap the root application context as usual using ContextLoaderListener -->

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<!-- Declare a Spring MVC DispatcherServlet as usual -->

<servlet>

<servlet-name>dispatcher</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->

<init-param>

<param-name>contextClass</param-name>

<param-value>

org.springframework.web.context.support.AnnotationConfigWebApplicationContext

</param-value>

</init-param>

<!-- Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified @Configuration classes -->

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>com.howtodoinjava.web.MvcConfig</param-value>

</init-param>

</servlet>

<!-- map all requests for /app/* to the dispatcher servlet -->

<servlet-mapping>

<servlet-name>dispatcher</servlet-name>

<url-pattern>/app/*</url-pattern>

</servlet-mapping>

</web-app>
9、怎样用注解的方式配置Spring?

Spring在2.5版本以后开始支持用注解的方式来配置依赖注入。可以用注解的方式来替代XML方式的bean描述,可以将bean描述转移到组件类的内部,只需要在相关类上、方法上或者字段声明上使用注解即可。注解注入将会被容器在XML注入之前被处理,所以后者会覆盖掉前者对于同一个属性的处理结果。

注解装配在Spring中是默认关闭的。所以需要在Spring文件中配置一下才能使用基于注解的装配模式。如果你想要在你的应用程序中使用关于注解的方法的话,请参考如下的配置。

<beans>

<context:annotation-config/>

<!-- bean definitions go here -->

</beans>
在 <context:annotation-config/>标签配置完成以后,就可以用注解的方式在Spring中向属性、方法和构造方法中自动装配变量。

下面是几种比较重要的注解类型:

@Required:该注解应用于设值方法。br/>@Autowired:该注解应用于有值设值方法、非设值方法、构造方法和变量。
@Qualifier:该注解和@Autowired注解搭配使用,用于消除特定bean自动装配的歧义。
JSR-250 Annotations:Spring支持基于JSR-250 注解的以下注解,@Resource、@PostConstruct 和 @PreDestroy。
10、请解释Spring Bean的生命周期?

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

Spring bean factory 负责管理在spring容器中被创建的bean的生命周期。Bean的生命周期由两组回调(call back)方法组成。

初始化之后调用的回调方法。
销毁之前调用的回调方法。
Spring框架提供了以下四种方式来管理bean的生命周期事件:

InitializingBean和DisposableBean回调接口
针对特殊行为的其他Aware接口
Bean配置文件中的Custom init()方法和destroy()方法br/>@PostConstruct和@PreDestroy注解方式
使用customInit()和 customDestroy()方法管理bean生命周期的代码样例如下:

<beans>

<bean id="demoBean" class="com.howtodoinjava.task.DemoBean"

init-method="customInit" destroy-method="customDestroy"></bean>

</beans>
更多内容请参考:Spring生命周期Spring Bean Life Cycle。

11、Spring Bean的作用域之间有什么区别?

Spring容器中的bean可以分为5个范围。所有范围的名称都是自说明的,但是为了避免混淆,还是让我们来解释一下:

singleton:这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例,单例的模式由bean factory自身来维护。
prototype:原形范围与单例范围相反,为每一个bean请求提供一个实例。
request:在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
Session:与请求范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。
全局作用域与Servlet中的session作用域效果相同。

更多内容请参考 : Spring Bean Scopes。

12、什么是Spring inner beans?

在Spring框架中,无论何时bean被使用时,当仅被调用了一个属性。一个明智的做法是将这个bean声明为内部bean。内部bean可以用setter注入“属性”和构造方法注入“构造参数”的方式来实现。

比如,在我们的应用程序中,一个Customer类引用了一个Person类,我们的要做的是创建一个Person的实例,然后在Customer内部使用。

public class Customer

{

private Person person;

//Setters and Getters

}

public class Person

{

private String name;

private String address;

private int age;

//Setters and Getters

}
内部bean的声明方式如下:

<bean id="CustomerBean" class="com.howtodoinjava.common.Customer">

<property name="person">

<!-- This is inner bean -->

<bean class="com.howtodoinjava.common.Person">

<property name="name" value="lokesh" />

<property name="address" value="India" />

<property name="age" value="34" />

</bean>

</property>

</bean>
13、Spring框架中的单例Beans是线程安全的么?

Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Spring bean并没有可变的状态(比如Serview类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多种状态的话(比如 View Model 对象),就需要自行保证线程安全。

最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“prototype”。

由于篇幅限制,剩下的内容下次为大家分享。

喜欢这篇文章的话,可以为作者点个喜欢,点下关注,每天都会分享Java相关文章!

还有不定时的福利赠送,包括整理的面试题,学习资料,源码等~~

一篇文章带你了解spring框架

原文地址:https://blog.51cto.com/14440597/2419143

时间: 2024-10-07 07:11:05

一篇文章带你了解spring框架的相关文章

一篇文章带你搞懂spring全家桶套餐

spring全家桶里都有哪些食物 上期我们讲了spring和springmvc两个框架的基础知识和学习路线,而这期内容,我们将围绕着spring全家桶展开来讨论. 大家应该都知道,按照出现的顺序,spring全家桶大概包含了spring.springmvc.springboot以及springcloud,从开胃小菜spring到满汉全席springcloud,spring全家桶可谓Java工程师的必备大餐,那么,我们不妨先来看看,spring全家桶是如何从光杆司令spring发展到如今的庞大家族

一篇文章带你深入了解Dubbo分布式服务框架

一.产生的背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进.下面我们用一个图来具体说明架构和开发框架的演进过程.单一应用架构当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本.此时,用于简化增删改查工作量的数据访问框架(ORM)是关键. 垂直应用架构当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率.此时,用于加速前端

一篇文章带你深入理解Zookeeper

随着互联网技术的发展,大型网站需要的计算能力和存储能力越来越高.网站架构逐渐从集中式转变成分布式. 虽然分布式和集中式系统相比有很多优势,比如能提供更强的计算.存储能力,避免单点故障等问题.但是由于采用分布式部署的方式,就经常会出现网络故障等问题,并且如何在分布式系统中保证数据的一致性和可用性也是一个比较关键的问题. 分布式的工作方式有点类似于团队合作.当有一项任务分配到某个团队之后,团队内部的成员开始各司其职,然后把工作结果统一汇总给团队主管,由团队主管再整理团队的工作成果汇报给公司. 但是,

阿里架构师用一篇文章带你详解SpringBoot注解

一.注解(annotations)列表@SpringBootApplication:包含了@ComponentScan.@Configuration和@EnableAutoConfiguration注解.其中@ComponentScan让Spring Boot扫描到Configuration类并把它加入到程序上下文. @Configuration 等同于spring的XML配置文件:使用java代码可以检查类型安全. @EnableAutoConfiguration 自动配置. @Compone

一篇文章带你快速入门createjs

开始用createjs这个框架的时候,发现网上的相关教程还是挺少的,所以写一篇文章,方便日后查看. createjs简介 官网:http://www.createjs.cc/ createjs中包含以下四个部分: EaselJS:用于 Sprites.动画.向量和位图的绘制,创建 HTML5 Canvas 上的交互体验(包含多点触控) TweenJS:用于做动画效果 SoundJS:音频播放引擎 PreloadJS:网站资源预加载 类似于SoundJS,PreloadJS,如果自己处理起来比较方

一篇文章带你入门Linux——马哥Linux基础学习笔记

1.课程体系: 中级: 初级:系统基础 中级:系统管理.服务安全及服务管理.Shell脚本: 高级: MySQL数据库: cache & storage 集群: Cluster lb: 4layer 7layer ha: 分布式: zookeeper 分布式文件系统 虚拟化技术: xen kvm Openstack:IAAS云: 运维工具: ansible puppet(ruby), saltstack(python) 监控工具: zabbix 大数据处理: hadoop spark, stor

蚂蚁技术专家:一篇文章带你学习分布式事务

小蚂蚁说: 分布式事务是企业集成中的一个技术难点,也是每一个分布式系统架构中都会涉及到的一个东西,特别是在这几年越来越火的微服务架构中,几乎可以说是无法避免,本文就围绕分布式事务各方面与大家进行介绍. 一. 事务 1.1 什么是事务 数据库事务(简称:事务,Transaction)是指数据库执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成. 事务拥有以下四个特性,习惯上被称为ACID特性: 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要

一篇文章带你了解网络爬虫的概念及其工作原理

众所周知,随着计算机.互联网.物联网.云计算等网络技术的风起云涌,网络上的信息呈爆炸式增长.毋庸置疑,互联网上的信息几乎囊括了社会.文化.政治.经济.娱乐等所有话题.使用传统数据收集机制(如问卷调查法.访谈法)进行捕获和采集数据,往往会受经费和地域范围所限,而且还会因其样本容量小.信度低等因素导致收集的数据往往与客观事实有所偏颇,有着较大的局限性. 网络爬虫通过统一资源定位符URL (Uniform ResourceLocator)来查找目标网页,将用户所关注的数据内容直接返回给用户,并不需要用

一篇文章带你解析,乐观锁与悲观锁的优缺点

乐观锁与悲观锁 概述 乐观锁 总是假设最好的情况,每次去读数据的时候都认为别人不会修改,所以不会上锁, 但是在更新的时候会判断一下在此期间有没有其他线程更新该数据, 可以使用版本号机制和CAS算法实现. 乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁. 在Java中java.util.concurrent.atomic包下面的原子变量类就是基于CAS实现的乐观锁. 悲观锁 总是假设最坏的情况,每次去读数据的时候都认为别