spring实战笔记_第2章

一、spring装配Bean

在Spring中,对象无需自己查找或创建与其所关联的其他对象。相反,容器负责把需要相互协作的对象引用赋予各个对象。主要有三种装配bean的方式:

1.在XML中进行显式配置。

2.在Java中进行显式配置。

3.隐式的bean发现机制和自动装配。

三种装配风格可以相互配合,但建议是尽可能地使用自动配置的机制。显式配置越少越好。当你必须要显式配置bean的时候(比如,有些源码不是由你来维护的,而当你需要为这些代码配置bean的时候),推荐使用类型安全并且比XML更加强大的JavaConfig。最后,只有当你想要使用便利的XML命名空间,并且在JavaConfig中没有同样的实现时,才应该使用XML。

二、自动化装配bean

Spring从两个角度来实现自动化装配:

组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。

自动装配(autowiring):Spring自动满足bean之间的依赖。

组件扫描和自动装配组合在一起就能发挥出强大的威力,它们能够将你的显式配置降低到最少。

2.1组件扫描

分为两个步骤:

1.定义带@Component注解的类

2.启动组件扫描,命令其去寻找带有@Component注解,并为其创建bean

         1)配置类启动组件扫描

         2)使用XML来启动组件扫描

代码详情:

//定义接口可以有多个实现,将CD播放器的任意实现与CD本身的耦合降低到了最小的程度。
public interface CompactDisc{
	void play();
}

//1.定义带@Component注解的类
@Component
//表明该类会作为组件类,并告知Spring要为这个类创建bean,不需要显式地配置这个bean
//@Compnent("lonelyHeartClub"):将该bean的id设置为lonelyHeartsClub
//@Named("lonelyHeartClub"):为bean设置id;
// Spring应用上下文中所有的bean都会给定一个ID。尽管我们没有明确地为SgtPeppersbean设置ID,但Spring会根据类名为其指定一个ID。具体来讲,这个bean所给定的ID为sgtPeppers,也就是将类名的第一个字母变为小写。
pubic class SgtPeppers implements CompactDisc{
	private String title="sgt,";
	private String artist="the Beatles";
	
	pulic void play(){
		System.out.println("play"+title+"by"+"artist");
	}
}
//2.启动组件扫描,命令其去寻找带有@Component注解,并为其创建bean
@Configuration
//配置类
@ComponentScan
//启动组件扫描,默认会扫描与配置类相同的包.Spring将会扫描这个包以及这个包下的所有子包,查找带有@Component注解的类。
//@ComponentScan("soundsystem"):设置基础包,扫描不同的包
//@ComponentScan(basePackages="soundsystem"):设置基础包
//@ComponentScan(basePackages={"soundsystem","video"}):设置多个基础包,只需要将basePackages属性设置为要扫描包的一个数组即可:
//@ComponentScan(basePackages={CDPlayer.class,DVDPlayer.class}):将basePackages指定为包中所包含的类或接口
public class CDPlayConfig{

}

//使用XML来启动组件扫描
<context:component-scan base-package="soundsystem"/>

2.2自动装配

自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。为了声明要进行自动装配,我们可以借助Spring的@Autowired注解。

1.构造器自动装配

在类的构造器上添加了@Autowired注解,这表明当Spring创建CDPlayerbean的时候,会通过这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean。

         1)如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。

         @Autowired(required=false)

  为了避免异常的出现,你可以将@Autowired的required属性设置为false:将required属性设置为false时,

 Spring会尝试执行自动装配,但是如果没有匹配的bean的话,Spring将会让这个bean处于未装配的状态。

         2)如果有多个bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个bean进行自动装配

         3)可以使用@Injecct(java依赖注入规范)代替@Autowired(spring特有的注解)

2.setter自动装配

         @Autowired用在属性的Setter方法上。在Spring初始化bean之后,它会尽可能得去满足bean的依赖。

3.      @Autowired注解可以用在类的任何方法上,由spring进行依赖注入

         不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法参数上所声明的依赖。

代码示例:

@Component
public class CDPlayer implements MediaPlayer{
	private CompactDisc cd;
	
	@Autowired
	public CDPlayer(CompactDisc cd){
		this.cd=cd;
	}
	@Autowired
	pubic void setCompactDisc(CompactDisc cd){
		this.cd=cd;
	}
	
	@Autowired
	pubic void insertDisc(CompactDisc cd){
		this.cd=cd;
	}
	
	pubic void play(){
		cd.play();
	}	
}

三、通过Java代码装配bean

有时必须使用显式配置的方式;如,你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了。

3.1 java配置的优势:

JavaConfig是更好的方案,因为它更为强大、类型安全并且对重构友好。因为它就是Java代码,就像应用程序中的其他Java代码一样。尽管它与其他的组件一样都使用相同的语言进行表述,但JavaConfig是配置代码。这意味着它不应该包含任何业务逻辑,JavaConfig也不应该侵入到业务逻辑代码之中,最好能够放在独立的包中。

3.2配置bean

         1).@Bean(name="lonelyHeartsClubBand")

         默认情况下,bean的ID与带有@Bean注解的方法名是一样的。在本例中,bean的名字将会是sgtPeppers。如果你想为其设置成一个不同的名字的话,那么可以重命名该方法,也可以通过name属性指定一个不同的名字:

3.3装配bean

1.构造器注入:

1)在JavaConfig中装配bean的最简单方式就是引用创建bean的方法。

       2)使用@bean,表明这个方法会创建一个bean实例并将其注册到Spring应用上下文中。所创建的beanID为cdPlayer,与方法的名字相同。

         3)调用方式:Spring将会拦截所有对sgtPeppers()的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。

在软件领域中,我们完全可以将同一个SgtPeppers实例注入到任意数量的其他bean之中。默认情况下,Spring中的bean都是单例的,我们并没有必要为第二个CDPlayer bean创建完全相同的SgtPeppers实例。所以,Spring会拦截对sgtPeppers()的调用并确保返回的是Spring所创建的bean,也就是Spring本身在调用sgtPeppers()时所创建的CompactDiscbean。因此,两个CDPlayer bean会得到相同的SgtPeppers实例。

4)使用请求参数:这种方式不会要求将CompactDisc必须声明到同一个配置中,实际上它可以通过组件扫描功能自动发现或者通过XML来进行配置,spring都会将其传入配置方法中,并用来创建CDPlayer Bean。

代码详情:


@Configuration
//@Configuration注解表明这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。
public class CDPlayerConfig{
	//1.声明简单的bean
	@Bean
	//@Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean。
	pubic CompactDisc sgtPeppers(){
		return new SgtPeppers();
		/*
			java声明Bean,可以发挥java的全部功能,如:在一组CD中随机选择一个CompactDisc来播放:
			@Bean
			public CompactDisc randomBeatlesCD(){
				int choice=(int)Math.floor(Math.random()*4);
				if(choice==0){
					return new SgtPeppers();
				}else if(choice==1){
					return new WhiteAlbum();
				}else if(choice==2){
					return new HardDayNight();
				}else{
					return new Revolver();
				}
			}
		*/
	}
	
	//2.java装配bean
	@Bean
	//在JavaConfig中装配bean的最简单方式就是引用创建bean的方法。
	public CDPlayer cdPlayer(){
		return new CDPlayer(sgtPeppers());
	}
	
	/*
	关于调用方式:
	@Bean
	public CDPlayer cdplayer(){
		return new CDPlayer(sgtPeppers());
	}
	@Bean
	public CDPlayer annotherCDPlayer(){
		return new CDPlayer(sgtPeppers());
	}
	//两个CDPlayer调用的是同一个SgtPeppers实例
    */
@Beanpublic CDPlayer cdPlayer(CompactDisc compactDisc){return new CDPlayer(compactDisc);}/*1.cdPlayer()方法请求一个CompactDisc作为参数,spring自动装配一个CompactDisc到配置方法中,然后方法体就可以按照合适的方式来使用它。*/}

2.setter注入:

//setter方法的DI配置
	@Bean
	pubic CDPlayer cdPlayer(CompactDisc compactDisc){
		CDPlayer cdPlayer=new CDPlayer(compactDisc);
		cdPlayer.setCompactDisc(compactDisc);
		return cdPlayer;
	}
	//带有@Bean注解的方法可以采用任何必要的Java功能来产生bean实例。构造器和Setter方法只是@Bean方法的两个简单样例
}

四、通过XML装配bean

         在Spring刚刚出现的时候,XML是描述配置的主要方式。在Spring的名义下,我们创建了无数行XML代码。在一定程度上,Spring成为了XML配置的同义词。因此理解已经存在的springXML配置十分重要。

4.1 SpringXML配置


4.2XML配置文件

1.配置bean

bean元素的属性如下:

1)class:

         1)创建这个bean的类通过class属性来指定的,并且要使用全限定的类名。

         2)在本例中,bean的ID将会是“soundsystem.SgtPeppers#0”。其中,“#0”是一个计数的形式,用来区分相同类型的其他bean。如果你声明了另外一个SgtPeppers,并且没有明确进行标识,那么它自动得到的ID将会是“soundsystem.SgtPeppers#1”。

2)id:借助id属性,为每个bean设置一个你自己选择的名字

3)声明bean的特征:

         1)声明即实例化:当Spring发现这个<bean>元素时,它将会调用SgtPeppers的默认构造器来创建bean。

         2)class属性不接受类型检查,改变类名就会出错

2.装配bean

1)构造器注入:xml元素和c命名空间

C命名空间的规则如下:

属性名以“c:”开头,也就是命名空间的前缀。接下来就是要装配的构造器参数名,在此之后是“-ref”,这是一个命名的约定,它会告诉Spring,正在装配的是一个bean的引用,这个bean的名字是compactDisc,而不是字面量“compactDisc”。

代码详情:

//XML配置文件的根元素
<beans>
<bean id="compactDisc" class="soundsystem.SgtPeppers">


//构造器注入
	//XML元素
	<constructor-arg ref="compactDisc"/>
	//c命名空间
	/*
	1.构造器参数名
		<bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc"/>
	2.使用参数在整个参数列表中的位置信息:
		<bean id="cdPlayer" class="soundsystem.CDPlayer" c:_0-ref="compactDisc"/>
	*/
</bean>
</beans>

(1)注入对象:ref

(2)将字面变量值装配对象

代码详情:

//将字面变量值装配对象
public class BlankDisc implements CompactDisc{
	private String title;
	private String artist;
	
	public BlankDisc(String title,String artist){
		this.title=title;
		this.artist=artist;
	}
	public void play(){
		System.our.println("playing"+title+"by"+artist);
	}
	
}
//xml元素
<bean id="compactDisc"
		class="soundsystem.BlankDisc">
	<constructor-arg value="sgt"/>
	<constructor-arg value="the Beatles">
</bean>
//c命名空间
//1.引用参数名字
<bean id="compactDisc"
			class="soundsystem.BlankDisc"
			c:_title="sgt"
			c:_artist="the Beatles"/>
//2.通过参数索引匹配
<bean id="compactDisc"
			class="soundsystem.BlankDisc"
			c:_0="sgt"
			c:_1="the Beatles"/>
(3)装配集合:

在装配集合方面,<constructor-arg>比c-命名空间的属性更有优势。目前,使用c-命名空间的属性无法实现装配集合的功能。

代码详情:

//装配集合

public class BlankDisc implements CompactDisc{
	private String title;
	private String artist;
	private List<String> tracks;
	
	public BlankDisc(String title,String artist,List<String> tracks){
		this.title=title;
		this.artist=artist;
		this.tracks=tracks;
	}
	
	public void play(){
		System.out.println("play"+title+"by"+artist);
		for(String track:tracks){
			System.out.println("track:"+track);
		}
	}
}

<bean id="compactDisc" class="soundsystem.BlankDisc">
	<constructor-arg value="sgt"/>
	<constructor-arg value="the Beatles"/>
	<constructor-arg>
		<list>
			<value>sgt</value>
			<value>with</value>
			<value>getting</value>
			<value>fixing</value>
		</list>
		
	/*类似的还有
	1.对象集合
	<list>
		<ref bean="sgtPeppers"/>
		<ref bean="whiteAlbum"/>
		<ref bean="revolver"/>
	</list>
	2.set集合
	如果是Set的话,所有重复的值都会被忽略掉,存放顺序也不会得以保证。
	<set>
			<value>sgt</value>
			<value>with</value>
			<value>getting</value>
			<value>fixing</value>
	</set>
	*/
	</constructro-arg>
</bean>

2)setter注入:xml元素和P命名空间

P命名空间规则如下:

首先,属性的名字使用了“p:”前缀,表明我们所设置的是一个属性。接下来就是要注入的属性名。最后,属性的名称以“-ref”结尾,这会提示Spring要进行装配的是引用,而不是字面量。

(1)该选择构造器注入还是属性注入呢?

作为一个通用的规则,对强依赖使用构造器注入,而对可选性的依赖使用属性注入。

(2)setter方法不再要求我们装配任何的属性,如果没有setter注入代表所有属性为空

//setter注入
<bean id="cdPlayer"
        class="soundsystem.CDPlayer">
	<property name="compactDisc" ref="compactDisc">
</bean>

<bean id="cdPlayer"
	class="soundsystem.CDPlayer"
	p:compactDisc-ref="compactDisc"/>

(3)字面变量,集合注入属性中,同构造器注入。还有util:list集合。

//util-命名空间实现集合注入.<util:list>元素会创建一个列表的bean
<util:list id=trackList>
	value>sgt</value>
	<value>with</value>
	<value>getting</value>
	<value>fixing</value>
</util:list>

<bean id="compactDisc"
	class="soundsystem.BlankDisc"
        p:title="sgt"
	p:artist="the Beatles"
	p:tracks-ref="trackList"/>

五、导入和混合配置

5.1自动装配:

在自动装配时,它并不在意要装配的bean来自哪里。自动装配的时候会考虑到Spring容器中所有的bean,不管它是在JavaConfig或XML中声明的还是通过组件扫描获取到的。

5.2在JavaConfig中引用XML配置

         1.将两个config类组合到一起

1. 将两个config类组合到一起
	//1.在CDPlayerConfig中使用@Import注解导入CDConfig:
@Configuration
pubic class CDConfig{
	@Bean
	public CompactDisc compactDisc(){
		return new SgtPeppers();
	}
}

@Configuration
@Import(CDConfig.class)
public class CDPlayerConfig{
	@Bean
	public CDPlayer cdPlayer(CompactDisc compactDisc){
		return new CDPlayer(compactDisc);
	}

//2.不在CDPlayerConfig中使用@Import,创建一个更高级别的SoundSystemConfig,在这个类中使用@Import将两个配置类组合在一起:
@Configuration
@Import({CDPlayerConfig.class,CDConfig.class})
public class SoundSystemConfig{
	
}

2. .bean配置在XML中,spring同时加载xml配置和java配置

         两个bean——配置在JavaConfig中的CDPlayer以及配置在XML中BlankDisc——都会被加载到Spring容器之中。因为CDPlayer中带有@Bean注解的方法接受一个CompactDisc作为参数,因此BlankDisc将会装配进来,此时与它是通过XML配置的没有任何关系。

//1.bean配置在XML中,spring同时加载xml配置和java配置
@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-cofig.xml");
public class SoundSystemConfig{
	
}

5.3. 在XML配置中引用JavaConfig

1.两种配置——其中一个使用XML描述,另一个使用Java描述——被组合在了一起。

<bean class="soundsystem.CDConfig"/>
<bean id="cdPlayer"
			class="soundsystem.CDPlayer"
			c:cd-ref="compactDisc"/>
2.创建一个更高层次的配置文件,这个文件不声明任何的bean,只是负责将两个或更多的配置组合起来。
<bean class="soundsystem.CDConfig"/>
<import resource="cdplayer=config.xml"/>

















  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值