刚开始学习Spring,看书的过程中做一些笔记,并对一些知识点做记录,以便之后回顾。
第1章 Spring之旅
1.1 简化Java开发
依赖注入DI(Dependency Injection)
好处:松耦合 实现方式之一:构造器注入(constructor injection)
一些概念:
装配:创建应用组件之间协作的行为。Spring有多种装配方式,采用XML是常见的一种装配方式。
应用切面AOP(Aspect oriented programming)
面向切面编程往往被定义为促使软件系统实现关注点分离的一项技术。
- 前置通知 - before advice
- 切入点
- 后置通知 - after advice
使用模板消除样板式代码
模板技术 例如:JdbcTemplate
1.2 容纳你的Bean
使用应用上下文
Spring自带了多种类型的应用上下文
- AnnotationConfigApplicationContext
- AnnotationConfigWebApplicationContext
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
- XmlWebApplicationContext
bean的生命周期
通过实现不同的接口,可以做不同的功能初始化.包括销毁也可以通过实现特定接口或者函数进行特定功能处理。
第2章 装配Bean
2.1 spring配置的可选方案
- 在XML中进行显示配置
- 在java中进行显示配置
- 隐式的bean发现机制和自动装配
2.2 自动化装配bean
- 组件扫描(component scanning)
- 自动装配(autowriting)
2.2.1 创建可被发现的Bean:
- 定义接口
- 接口实现类(继承类)添加@Component注解
- 添加一个类添加@ComponentScan注解,启用组件扫描(也可以通过XML配置启用组件扫描)
- 再需要注入的变量、构造方法、方法上添加@Autowired注解实现自动注入,也就是自动装配。
public interface CompactDisc {
void play();
}
@Component
public class SgtPeppers implements CompactDisc {
private String title = "Sgt. pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";
@Override
public void play() {
System.out.println("Playing " + title + " by " + artist);
}
}
@ComponentScan注解启用组件扫描
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
通过xml启用组件扫描
<context:component-scan base-package="soundsystem" />
Test
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
}
2.2.2 为组件扫描的bean命名
@Component("lonelyHeartsClub")
@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
...
}
@Named("lonelyHeartsClub")
@Named("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
...
}
2.2.3 设置组件扫描的基础包
@ComponentScan("soundsystem")
@Configuration
@ComponentScan("soundsystem")
public class CDPlayerConfig {
}
@ComponentScan(basePackages="soundsystem")
@Configuration
@ComponentScan(basePackages="soundsystem")
public class CDPlayerConfig {
}
@ComponentScan(basePackages={"soundsystem", "video"})
@Configuration
@ComponentScan(basePackages={"soundsystem", "video"})
public class CDPlayerConfig {
}
@ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})
@Configuration
@ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})
public class CDPlayerConfig {
}
2.2.4 通过为Bean添加注解实现自动装配
@Autowired @Inject
@Component
public class CDPlayer implements MediaPlayer {
private CompactDisc cd;
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
public void play() {
cd.play();
}
}
Setter方式
@Autowired
public void setCompactDisc(CompactDisc cd) {
this.cd = cd;
}
方法
@Autowired
public void insertDisc(CompactDisc cd) {
this.cd = cd;
}
非强制自动装配
@Autowired(required = false)
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
2.2.5 验证自动装配
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Autowired
private MediaPlayer player;
@Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
@Test
public void play() {
player.play();
}
}
2.3 通过Java代码装配bean
2.3.1 创建配置类
@Configuration
public class CDPlayerConfig {
}
2.3.2 声明简单的bean
@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
为bean设置不同的名字方法2种:
@Bean(name="longlyHeartsClubBand")
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
@Bean
public CompactDisc longlyHeartsClubBand() {
return new SgtPeppers();
}
2.3.3 借助JavaConfig实现注入
方法1:引用创建bean方法
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(sgtPeppers());
}
@Bean
public CDPlayer anotherCDPlayer() {
return new CDPlayer(sgtPeppers());
}
方法2:自动装配
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
方法3:自动装配setter
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
CDPlayer cdPlayer = new CDPlayer(compactDisc);
cdPlayer.setCompactDisc(compactDisc);
return cdPlayer;
}
2.4 通过XML装配bean
2.4.2 声明一个简单的bean
<bean class="soundsystem.SgtPeppers" />
<bean id="compactDisc" class="soundsystem.SgtPeppers" />
2.4.3 借助构造器注入初始化bean
使用<constructor-arg>元素
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<constructor-arg ref="compactDisc" />
</bean>
使用Spring3.0所引入的c-命名空间(需要在xml文件中启用c-命名空间)
方法1:
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc" />
方法2:
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:_0-ref="compactDisc" />
方法3:
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:_-ref="compactDisc" />
将字面量注入到构造器
package soundsystem;
public class BlankDisc implements CompactDisc {
private String title;
private String artist;
public BlankDisc(String title, Strng artist) {
this.title = title;
this.artist = artist;
}
public void play() {
System.out.println("Playing " + title + " by " + artist);
}
}
使用<constructor-arg>
<bean id="compactDisc" class="soundsystem.BlankDisc">
<constructor-arg value="sgt. pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
</bean>
使用c-命名空间
<bean id="compactDisc"
class="soundsystem.BlankDisc"
c:_title="sgt. pepper's Lonely Hearts Club Band"
c:_artist="The Beatles" />
or
<bean id="compactDisc"
class="soundsystem.BlankDisc"
c:_0="sgt. pepper's Lonely Hearts Club Band"
c:_1="The Beatles" />
装配集合
package soundsystem;
public class BlankDisc implements CompactDisc {
private String title;
private String artist;
private List<String> tracks;
public BlankDisc(String title, Strng artist, List<String> tracks) {
this.title = title;
this.artist = artist;
this.tracks = tracks;
}
public void play() {
System.out.println("Playing " + title + " by " + artist);
for (String track : tracks) {
System.out.println("-Track: " + track);
}
}
}
传递null参数
<bean id="compactDisc" class="soundsystem.BlankDisc">
<constructor-arg value="sgt. pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
<constructor-arg><null/></constructor-arg>
</bean>
传递列表:
<bean id="compactDisc" class="soundsystem.BlankDisc">
<constructor-arg value="sgt. pepper's Lonely Hearts Club Band" />
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<value>sgt. pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting better</value>
<value>Fixing a Hole</value>
</list>
</constructor-arg>
</bean>
实现Bean引用列表的装配
public Discography(String artist, List<CompactDisc> cds) { ... }
<bean id="beatlesDiscography" class="soundsystem.Discography">
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<ref bean="sgtPeppers" />
<ref bean="whiteAlbum" />
<ref bean="HeadDaysNight" />
<ref bean="revolver" />
</list>
</constructor-arg>
</bean>
2.4.4 设置属性
public class CDPlayer implements MediaPlayer {
private CompactDisc compactDisc;
@Autowired
public void setCompactDisc(CompactDisc compactDisc) {
this.compactDisc = compactDisc;
}
public void play() {
compactDisc.play();
}
}
无参数构造
<bean id="cdPlayer" class="soundsystem.CDPlayer" />
通过属性设置
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<property name="compactDisc" ref="compactDisc" />
</bean>
使用p-命名空间(需要xml启动p-命名空间)
<bean id="cdPlayer"
class="soundsystem.CDPlayer"
p:compactDisc-ref="compactDisc" />
将字面量注入到属性
public class BlankDisc implements CompactDisc {
private String title;
private String artist;
private List<String> tracks;
public void setTitle(String title) {
this.title = title;
}
public void setArtist(String artist) {
this.artist = artist;
}
public void setTracks(List<String> tracks) {
this.tracks = tracks;
}
@Override
public void play() {
System.out.println("Playing " + title + " by " + artist);
for (String track : tracks) {
System.out.println("-Track: " + track);
}
}
}
空构造
<bean id="reallyBlankDisc" class="soundsystem.BlankDisc" />
属性设置
<bean id="reallyBlankDisc" class="soundsystem.BlankDisc">
<property name="title" value="sgt. pepper's Lonely Hearts Club Band" />
<property name="artist" value="The Beatles" />
<property name="tracks">
<list>
<value>sgt. pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting better</value>
<value>Fixing a Hole</value>
</list>
</property>
</bean>
使用p-命名空间,并混合使用
<bean id="reallyBlankDisc" class="soundsystem.BlankDisc"
p:title="sgt. pepper's Lonely Hearts Club Band"
p:artist="The Beatles">
<property name="tracks">
<list>
<value>sgt. pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting better</value>
<value>Fixing a Hole</value>
</list>
</property>
</bean>
使用Spring util-命名空间(需要启用XML的util-命名空间)
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util-4.0.xsd">
<util:list id="trackList">
<value>sgt. pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting better</value>
<value>Fixing a Hole</value>
</util:list>
<bean id="reallyBlankDisc" class="soundsystem.BlankDisc"
p:title="sgt. pepper's Lonely Hearts Club Band"
p:artist="The Beatles"
p:tracks-ref="trackList" />
Spring util-命名空间的元素
<util-constant>
<util-list>
<util-map>
<util-properties>
<util-property-path>
<util-set>
2.5 导入和混合配置
2.5.1 再JavaConfig中引用XML配置
@Configuration
public class CDConfig {
@Bean
public CompactDisc compactDisc() {
return new SgtPeppers();
}
}
使用@Import导入
@Configuration
@Import(CDConfig.class)
public class CDPlayerConfig {
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
}
使用@Import组合
@Configuration
public class CDPlayerConfig {
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
}
@Configuration
@Import({CDPlayerConfig.class, CDConfig.class})
public class SoundSystemConfig {
}
cd-config.xml
<bean id="compactDisc" class="soundsystem.BlankDisc" c:_0="Sgt. pepper's Lonely Hearts Club Band" c:_1="The Beatles">
<constructor-arg>
<value>Sgt. pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting better</value>
<value>Fixing a Hole</value>
</constructor-arg>
</bean>
@Configuration
public class CDPlayerConfig {
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
}
@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {
}
2.5.2 在XML配置中引用JavaConfig
方案1:xml配置使用import引入xml-config
cd-config.xml
<bean id="compactDisc" class="soundsystem.BlankDisc" c:_0="Sgt. pepper's Lonely Hearts Club Band" c:_1="The Beatles">
<constructor-arg>
<value>Sgt. pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting better</value>
<value>Fixing a Hole</value>
</constructor-arg>
</bean>
<import resource="cd-config.xml" />
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc" />
方案2:xml配置通过bean方式导入JavaConfig
@Configuration
public class CDConfig {
@Bean
public CompactDisc compactDisc() {
return new SgtPeppers();
}
}
<bean class="soundsystem.CDConfig" />
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc" />
方案3:更高层次xml配置文件组合JavaConfig与xml配置
cdplayer-config.xml
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc" />
<bean class="soundsystem.CDConfig" />
<import resource="cdPlyaer-config.xml" />