Spring的定义
对DI的初步理解
对AOP的初步理解
对DI的深入探究
对AOP的深入探究
Spring的事务管理
Spring MVC
spring的特性之一是DI,而DI的关键在于bean的装配,即创建系统各组件之间的协作关系。而组件是存活在spring容器中的,容器是spring的核心,spring提供多种容器的实现。第一种是bean工厂,即BeanFactory接口;第二种是ApplicationContext接口。BeanFactory是最简单的容器,只提供了基础的依赖注入支持;而后者是在BeanFactory基础之上的,提供了更多的系统服务。
Spring中有多种Beanfactory的实现,其中最常见的一种就是根据XML配置文件来装载bean的XmlBeanFactory。但是要创建一个XmlBeanFactory实例需要传递一个Resource类型的实例给构造函数,正是此Resource对象提供了XML文件给BeanFactory。因此,创建一个Beanfactory可以这样做:
BeanFactory factory = new XmlBeanFactory( new FileSystemResource( “C:/abc.xml” ) );
这是通过文件系统来读取xml文件初始化BeanFactory的,还有许多种方法,比如ClassPathResource、InputStreamResource等。但是,执行上述代码并没有实例化任何一个bean,要实例化一个bean还要调用getBean方法:factory.getBean(“beanName”); 当调用过该方法之后,BeanFactory会依据xml配置文件设置该bean的属性并实例化它。
然而,很多时候我们需要一些更强大的功能,这时我们就需要用到ApplicationContext了。而且在大多数情况下,我们是会使用后者的。然而spring的应用上下文对象也很好用,载入一个上下文很简单:
ApplicationContext context = new FileSystemXmlApplicationContext(“C:/abc.xml”);
或者像这样:
ApplicationContext context = new ClassPathXmlApplicationContext(“abc.xml”);
这时要获得一个bean和BeanFactory时的一样,毕竟ApplicationContext是继承自BeanFactory的。
下面将通过一些例子来由浅入深的进行阐述。一年一度的Java天才大赛来了,每个参赛者都可以表演任何节目。因此定义一个接口,每位参赛者都要实现该接口:
public interface Performer
{ public void perform(); }
首先出场的是一位魔术师,它是一个简单的bean:
public class Juggler implements Performer {
private int beanBags = 3;
public Juggler(int beanBags) {
this.beanBags = beanBags;
}
public void perform(){
System.out.println("JUGGLING " + beanBags + " BEANBAGS");
}
}
传统的注入该bean方式如下:
<bean id=”duke” class=”com.alibaba.Juggler” / >
spring容器装载该bean时,会调用该类的默认构造函数,因此该类的实例的beanBags变量的值是3。我们还可以通过如下的配置方法让该类的实例的变量值是15:
<bean id=”duke” class=”com.alibaba.Juggler” >
<constructor-arg value=”15” />
</bean>
这样,spring注入该bean的时候,就会调用该类的重载构造函数。如果对于一些特殊的构造函数的参数中包含对象的(非基本类型),可以通过如下方式指定参数的值:
<constructor-arg ref=”object-Bean-Id” />
其中“object-Bean-Id”就是另一个bean的id
下面,为了演示spring的setter注入方式,我们荣幸的请到了出色的乐器演奏家Kenny。
public class InstrumentKenny implements Performer
{
public void perform()
{
System.out.print("Playing " + song + " : ");
instrument.play();
}
private String song;
public void setSong(String song) {
this.song = song;
}
private Instrument instrument;
public void setInstrument(Instrument instrument) {
this.instrument = instrument;
}
}
当然,我们需要定义一个乐器接口Instrument:
public interface Instrument
{
public void play();
}
现在,我们创造一个萨克斯风乐器:
public class Saxophone implements Instrument
{
public void play()
{
System.out.println("TOOT TOOT TOOT");
}
}
这时,我们只需要进行如下配置,就可以让Kenny去演奏萨克斯风了:
<bean id="saxophone" class="com.alibaba.Saxophone" />
<bean id=”kenny” class=”com.alibaba.InstrumentKenny”>
<property name=”song” value=”Jingle bells” />
<property name=”instrument” ref=” saxophone” />
</bean>
其实我们会发现,使用setter注入和使用构造函数注入,没什么区别,代码几乎相同。如果,kenny很聪明并且还会演奏钢琴的话,我们只需要声明一个钢琴类,再修改一下配置文件,ref=” piano” 即可。几乎不需要修改任何已有代码,这样就实现了松耦合的目的。
现在,kenny可以演奏任何实现Instrument接口的乐器了,然而,这些乐器也可以被其他人所演奏,因此,就产生了乐器的个人卫生问题(萨卡斯风是要使用嘴吹的)。我们可以通过注入内部bean来解决这个问题:
<bean id=”kenny” class=”com.alibaba.InstrumentKenny”>
<property name=”song” value=”Jingle bells” />
<property name=”instrument”>
<bean class=”com.alibaba. saxophone” />
</property>
</bean>
内部bean不能被其他bean所复用,因此该bean也就没有必要有id属性。当然,在构造函数注入方式下也可以使用内部bean。
下面,将阐述一下spring的自动注入。spring提供了四种自动装配类型:byname、bytype、constructor、autodetect。其中,byname使用最为广泛。现在让我们来回忆一下kenny演奏萨克斯风的配置:
<bean id="saxophone" class="com.alibaba.Saxophone" />
<bean id=”kenny” class=”com.alibaba.InstrumentKenny”>
<property name=”song” value=”Jingle bells” />
<property name=”instrument” ref=” saxophone” />
</bean>
我们可以将上面的配置改成如下这样,以实现spring的自动注入:
<bean id=" instrument" class="com.alibaba.Saxophone" />
<bean id=”kenny” class=”com.alibaba.InstrumentKenny” autowire=”buName”>
<property name=”song” value=”Jingle bells” />
</bean>
然而,我们也可以使用混合的方式,如:在设置autowire=”byType”时,显式的装配某个bean,而不需要spring自己去寻找一个type相同的bean,以避免有多个相同类型的bean时spring抛出异常。
由此我们可以发现,spring的自动装配存在很多问题,其中最大的缺点就是缺乏代码的可读性和透明性。
我们已经了解了spring对bean的装载的基础知识。下面我们来说一下spring中bean的范围。在spring中,bean的范围可以是如下几种:singleton、prototype、request、session、global-session,比如:
<bean id=”” class=”” scope=”” />
其中,如果不指定scope的话,默认会是单例的,即singleton的,意思是在整个spring容器中,该bean只有一个实例;而prototype则与之相反,每次使用的时候都会创建一次。当然,我们也可以通过其他手段来实现单例:比如我们可以设置bean标签的factory-method属性来指定该类的工厂方法。
在bean生命周期中有两个重要的环节:初始化和销毁。为一个bean指定一个初始化方法和销毁方法很简单,只要设置bean标签的init-method属性和destroy-method即可。当然我们还有另一个方法:实现InitializingBean和DisposableBean接口,然后,在该类中实现afterPropertiesSet方法和destroy方法,以实现bean的初始化和销毁。
下面我们来看一下bean的继承。spring的bean标签中有两个属性:parent和abstract。前者相当于java里的extends,后者则是告诉spring容器,该bean不能被实例化。举个例子,前面我们说过,kenny是一个擅长吹萨克斯的选手,他的配置文件如下:
<bean id="saxophone" class="com.alibaba.Saxophone" />
<bean id=”kenny” class=”com.alibaba.InstrumentKenny”>
<property name=”song” value=”Jingle bells” />
<property name=”instrument” ref=” saxophone” />
</bean>
可是,这个比赛不止kenny一个人会吹萨克斯,现在又有一个david也吹萨克斯,而且也演奏“Jingle bells”。这样的话,如果配置两条除id以外都相同的bean多少有些累赘。这时我们就需要使用到bean的继承特性。配置如下:
<bean id=”baseSaxophonist” class=”com.alibaba.Instrument” abstract=”true” >
<property name=”song” value=”Jingle bells” />
<property name=”instrument” ref=” saxophone” />
</bean>
<bean id=”kenny” parent=”baseSaxophonist” />
当然,如果现在又来了一位选手,他会吹萨克斯,但是演奏的不是“Jingle bells”,这是否意味着已有的父bean不能使用了呢?当然不是的,我们还可以覆盖父bean的属性。比如:
<bean id=”frank” parent=”baseSaxophonist” >
<property name=”song” value=”another song” />
</bean>
然而,声明父bean时我们也可以不指定bean的class属性,具体的class由子bean去指定,这样,我们就可以将一些常用到的属性提出到父bean,让各个bean去继承,而各子bean不必是相同的类型。
分享到:
相关推荐
SPRING技术内幕:深入解析SPRING架构与设计原理SPRING技术内幕:深入解析SPRING架构与设计原理SPRING技术内幕:深入解析SPRING架构与设计原理SPRING技术内幕:深入解析SPRING架构与设计原理SPRING技术内幕:深入解析...
Springcloud学习笔记.md,Springcloud学习笔记.md,Springcloud学习笔记.md,Springcloud学习笔记.md,Springcloud学习笔记.md,Springcloud学习笔记.md,Springcloud学习笔记.md,Springcloud学习笔记.md,Spring...
这份"Spring学习笔记+学习源码.zip"资源包含了深入学习Spring及其相关技术的知识点,以及实践代码,对提升Spring技能将大有裨益。 首先,我们来详细讨论Spring框架的主要组件和功能: 1. **依赖注入(Dependency ...
读书笔记:学习《深入理解Spring Cloud与微服务构建》
读书笔记:学习《深入浅出Spring Boot 2.x》打好Spring Boot基础
### Spring学习笔记(精华全记录) #### Spring框架概述 Spring框架源自Rod Johnson的个人项目,最初于2002年末发布。Spring并非一开始就作为一个完整的框架出现,而是从一个项目逐步发展而来。随着项目的成熟,...
不过,从这个重复提及的信息来看,这可能是一个提供编程资源下载、学习资料分享的网站,对于想要深入学习Spring框架的开发者来说,可能是一个有用的资源。 整体而言,Spring框架作为Java企业应用开发的事实标准,其...
Spring学习笔记( spring视频笔记)
本资料“Spring学习笔记&源码”是基于网易云课堂黑马程序员的Spring四天精通课程,旨在帮助学习者深入理解和实践Spring框架。 笔记部分可能会涵盖以下内容: 1. **Spring概述**:介绍Spring框架的历史、特点和主要...
spring学习笔记
深入解析Spring架构原理与设计思想,探究Spring成功的奥秘。 揭开Spring源代码的神秘面纱,展示系统阅读开源软件源代码的方法和秘诀。 如果你正在思考下面这些问题,也许《Spring技术内幕:深入解析Spring架构...
SPRING技术内幕:深入解析SPRING架构与设计原理.pdf(带书签)
读书笔记:根据《深入理解Spring Cloud与微服务构建》编写的实例代码
根据提供的压缩包文件名,我们可以推测这是一个逐步学习Spring的系列笔记。从"Spring_day1"开始,可能涵盖了Spring的基础概念、环境搭建和基本配置。"Spring_day2"可能涉及了依赖注入和AOP的深入讲解。"Spring_day3...
2.iBatis2学习笔记:与Spring2的整合.doc 3.iBatis2学习笔记:单表映射 .doc 4.iBatis2学习笔记:SqlMap的配置总结(18条).doc 5.iBatis2学习笔记:入参和返回值的问题.doc 6.iBatis2学习笔记:一对多映射(双向)....
《SPRING技术内幕:深入...通过阅读《SPRING技术内幕:深入解析SPRING架构与设计原理》这本书,开发者可以深入了解Spring的内部工作机制,提升对Spring框架的使用水平,更好地利用Spring解决实际问题,提高开发效率。
Spring学习笔记(马士兵spring视频笔记).docSpring学习笔记(马士兵spring视频笔记).docSpring学习笔记(马士兵spring视频笔记).docSpring学习笔记(马士兵spring视频笔记).doc
### Spring学习笔记知识点详解 #### 一、Spring框架概述 **1.1 什么是Spring** Spring框架是一个开源的轻量级应用框架,主要用于简化企业级应用程序的开发过程。它的核心特性在于提供了一种灵活的方式来组织和...