您的位置:首页 > 编程语言 > Java开发

spring实战笔记_第2章

2018-03-31 19:57 204 查看

一、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();
}els
b105
e{
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"/>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: