一.自动化装配bean
1.1 创建可被发现的bean
@Component
这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean
启用组建扫描
注:@configuration:表明是一个配置类
@ComponentScan
public class CDPlayerConfig{
}
在XML中 <context: componnet-scan base-package="soundsystem">
1.2为组件扫描的bean命名
如果没有个bean设置ID,Spring会根据类名为其指定一个ID,默认名字就是把类名的第一个字母变为小写.
@Component("lonelyHeartsClub") //设置期望的ID
public class SgtPeppers implements CompactDisc{
}
另外还一种为bean命名的方式,使用Java依赖注入规范中所提供的@Named注解来为bean设置ID
@Named("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc{
}
1.3设置组件扫描的基础包
//直接在value属性中指明包的名称
@Configuration
@ComponentScan("soundsystem")
public class CDPlayerConfig{}
//通过basePackages属性配置
@Configuration
@ComponentScan(basePackages="soundsystem")
public class CDPlayerConfig{}
//设置多个基础包,用数组表示
@Configuration
@ComponentScan(basePackages={"soundsystem","video"})
public class CDPlayerConfig{}
//基础包以String类型表示是不安全的,如果重构代码的话,指定的基础包可能会出现错误,用指定为包中所包含的类或接口的方法
@Configuration
@ComponentScan(basePackageClasses={CDPlayer.class,DVDPlayer.class})
public class CDPlayerConfig{}
但是,很多对象会依赖其他对象才能完成任务,这样的话,我们需要有一种方法能够将组件扫描得到的bean和它们的依赖装配在一起,那就需要自动装配.
1.4通过bean添加注解实现自动装配
@Autowired
@Component
public class CDPlayer implements MediaPlayer{
private CompactDisc cd;
@Autowired//这表明当Spring创建CDPlayer bean的时候,会通过这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean.
public CDPlayer(CompactDisc cd){//构造器
this.cd = cd;
}
public void paly(){
cd.paly();
}
}
@Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上.比如说,如果CDPlayer有一个setCompactDisc()方法,那么可以采用如下的注解形式进行自动装配:
@Autowired
public void setCompactDisc(CompactDisc cd){
this.cd = cd;
}
但是如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常,为了避免异常的出现,你可以将@Autowired的requied属性设置为false
@Autowired(required=false)
public void setCompactDisc(CompactDisc cd){
this.cd = cd;
}
但是
一,把required属性设置为false时,你需要谨慎对待,如果代码中没有进行null检查的话,这个处于未装配的属性有可能会出现空指针异常.
二,如果有多个bean都能满足依赖关系的话,Spring将会抛出一个异常,表明没有明确指定要选择哪个bean进行自动装配,这个以后再讨论.
@Autowired可以换成@Inject,@Inject注解来源于Java依赖注入规范,该规范同时还为我们定义了@Named注解.
尽管@Inject和@Autowierd有细微的差别,但大多数场景下,它们都可以互换.
二 通过Java代码装配bean
有些情况下,比如说,要将第三方库的组件装配到你的应用中,就不能在它的类上添加@Component和@Autowired注解的,因此,就不能使用自动化装配的方案了.
在这种情况下,就需要采用显示装配的方式.在进行显示配置有Java和XML两种方案.
2.1创建配置类(JavaConfig类)
@Configuration
public class CDPlayerConfig{}
//创建JavaConfig类的关键在于为其添加@Configruation注解,表明这是一个配置类
2.2声明简单的bean
@Bean
public CompactDisc sgtPeppers(){
return new SgtPeppers();
}
//@Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文的bean,默认情况下,
bean的ID于带有@Bean注解的方法名一样,也可以重命名
@Bean(name="lonelyHeartsClubBand")
public CompactDisc sgtPeppers(){
return new SgtPeppers();
}
2.3借助JavaConfig实现注入
声明CompactDisc bean是非常简单,它自身没有其他依赖,但现在,我们需要声明CDPlayer bean,它依赖于CompactDisc,在JavaConfig中,如何将他们装配在一起呢?
在JavaConfig中装配bean的最简单方式就是 引用创建bean的方法.
@Bean
public CDPlayer cdPlayer(){
return new CDPlayer(sgtPeppers());
}
//因为sgtPeppers()方法上添加了@Bean注解,Spring将会拦截所有对它的调用,
//并确保直接返回该方法创建的bean,而不是每次都对其进行实际的调用.
默认情况下,Spring中的bean都是单例,所以,Spring会拦截对sgtPeppers()的调用并确保返回的是Spring所创建的bean,也就是Spring本身在调用sgtPeppers()时所创建的CompactDisc bean.
如果调用方法来引用bean的方式有点困惑,也可以这么理解
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
return new CDPlayer(compactDisc);
}
//在这里,cdPlayer()方法请求一个CompactDisc作为参数,当Springs调用cdPlayer()创建CDPlayer bean的时候,
//它会自动装配一个CompactDisc到配置方法之中,然后方法体按照合适的方法来使用它.
也可以通过Setter方法注入CompactDisc
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
CDPlayer cdPlayer = new CDPlayer(compactDisc);
cdPlayer.setCompactDisc(compactDisc);
return cdPlayer;
}
三 通过XML装配bean
3.1创建XML配置规范
<?xml version="1.0" encoding="UTF-8">
<beans xmlns="http://........"
xmlns:xsi="http://.....''>
<!-- configuration details go here -->
</beans>
//借助Spring Tool Suite 创建XML配置文件
3.2声明一个简单的<bean>
<bean class="soundsystem.SgtPeppers" />
//这里声明一个很简单的bean,因为没有明确给定ID,所以这个bean将会根据全限定类名来进行命名,
//这里的bean的ID将会是"soundsystem.SgtPeppers#0".其中,"#0"是一个计数的形式,来区分相同类型的bean.
//更好的方法是借助id属性
<bean id="compactDisc" class="soundsystem.SgtPeppers" />
//XML装配bean的缺点
//1.当Spring发现这个<bean>元素时,它将会调用SgtPeppers的默认构造器来创建bean.在XML配置中,bean的创建显得更加被动
//2.不如JavaConfig强大,在JavaConfig配置中,可以通过任何想象到的方法来创建bean实例(构造器,set方法等)
//3.在简单的<bean>声明中,将bean的类型以字符串的形式设置在了class属性中,不能保证设置给class属性的值是真正的类
//4.重命名了类,也会引起麻烦
3.3借助构造器注入初始化bean
有两种基本的配置方案可选择
1.<constructor-arg>元素
2.使用Spring3.0所引入的c-命名空间
(1)构造器注入--bean引用
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<constructor-arg ref="compactDisc">
</bean>
//当Spring遇到<bean>这个元素时,它会创建一个CDPlayer实例.<constructor-arg>元素会告知Spring要将
//一个ID为compactDisc的bean引用传递到CDPlayer的构造器中.
作为替代方案,也可以使用Spring的c-命名空间
要在XML的顶部声明其模式
<?xml version="1.0" encoding="UTF-8">
<beans xmlns="http://........"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:xsi="http://.....''>
<!-- configuration details go here -->
</beans>
然后可以使用它了
<bean id="cdPlayer" class="soundsystem.CDPlayer"
c:cd-ref="compactDisc">
//"c:" 命名空间的前缀
//"cd" 构造器参数名
//"-ref"注入bean引用
//"compactDisc" 要注入bean 的ID
如果在优化构建的过程,将调试标志移除掉,那么这种方式可能无法正常执行.代替方案
<bean id="cdPlayer" class="soundsystem.CDPlayer"
c:_0-ref="compactDisc">
//把参数名换成"0",也就是参数的索引,但XML中不允许数字作为属性的第一个字符,因此添加下划线"_"
如果只有一个参数,根本不用去标示参数
<bean id="cdPlayer" class="soundsystem.CDPlayer"
c:_-ref="compactDisc">
(2)将字面量注入到构造器中
之前是将对象的引用装配到依赖于它们的其他对象之中,如果有时候,我们需要做的只是用一个字面量值来配置对象.为了阐述这点,创建CompactDisc的一个新的实现
public class BlankDisc implements CompactDisc{
private String title;
private String artist;
public BlandDisc(String title,String artist){
this.title = title;
this.artist = artist;
}
public void paly(){
System.out.println("Playing"+title+"by"+artist);
}
}
这个于SgtPeppers不同,它可以设置任意想要的title和artist,我们可以已有的SgtPeppers替换为这个类
<bean id="compactDisc"
class="soundysytem.BlankDisc">
<constructor-arg value="Sgt.Peper's Lonely Hearts" />
<constructor-arg value="The beatles"/>
</bean>
这里再次使用<constructor-arg>元素进行构造器参数的注入,但是没有使用ref属性来引用其他的bean,而是使用了value属性,通过该属性表明给定的值要以字面量的形式注入到构造器之中.
如果要以c-命名空间,可以引用构造器参数名字
<bean id="compactDisc"
class="soundsystem.BlanDisc"
c:_title="Sgt.Peper's Lonely Hearts"
c:_artist="The beatles"/>
</bean>
可以看到,装配引用和装配字面量的区别在于去掉了-ref后缀,也可以这样通过参数索引
<bean id="compactDisc"
class="soundsystem.BlanDisc"
c:_0="Sgt.Peper's Lonely Hearts"
c:_1="The beatles"/>
</bean>
(3)装配集合
<bean id="compactDisc"
class="soundsystem.BlankDisc">
<constructor-arg value="Sgt.Peper's Lonely Hearts" />
<constructor-arg value="The beatles" />
<constructor-arg>
<list>
<value>Sgt. Pepper's Lonely Heats</value>
<value>With a Little Help</value>
<value>Lucy in the Sky</value>
<value>Getting Better</value>
<value>Fixing a Hole</value>
</list>
</constructor-arg>
</bean>
也可以使用<ref>元素代替<value>,实现bean引用列表的装配
假设你有一个Discography类,它的构造器如下
public Discography(String artist,List<CompactDisc> cds){...}
那么,可以采取如下的方式配置 Discography bean:
<bean id="beatlesDiscography" class="soundsystem.Discography">
<constructor-arg value="The Beatles" />
<constructor-arg>
<list>
<ref bean="sgtPeppers" />
<ref bean="whiteAlbum" />
...
</lsit>
</constructor-arg>
也可以使用<set>元素,set不重复,不能保证顺序,list可以重复,保证顺序
<bean id="compactDisc"
class="soundsystem.BlankDisc">
<constructor-arg value="Sgt.Peper's Lonely Hearts" />
<constructor-arg value="The beatles" />
<constructor-arg>
<set>
<value>Sgt. Pepper's Lonely Heats</value>
<value>With a Little Help</value>
<value>Lucy in the Sky</value>
<value>Getting Better</value>
<value>Fixing a Hole</value>
</set>
</constructor-arg>
</bean>
3.4设置属性
使用Spring XML实现属性注入,假设属性注入的CDPlayer如下
import soundsystem.CompactDisc;
import soundsystem.MediaPlayer;
public class CDPlayer implements MediaPlayer{
private CompactDisc compactDisc;
@Autowired
public void setCompactDisc(CompactDisc compactDisc){
this.compactDisc = compactDisc;
}
public void paly(){
compactDisc.play();
}
}
注入compactDisc属性
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<property name="compactDisc" ref="compactDisc" />
</bean>
//通过ref引用了ID为compactDisc的bean,将其注入到compactDisc属性中(通过setCompactDisc()方法)
使用p-命名空间,先声明
<?xml version="1.0" encoding="UTF-8">
<beans xmlns="http://........"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://.....''>
<!-- configuration details go here -->
</beans>
装配
<bean id="cdPlayer" class="soundsystem.CDPlayer"
p:compactDisc-ref="compactDisc" />
</bean>
//"p:" :前缀
//前面的compactDisc: 属性名
//-ref: 注入bean引用
//后面的compactDisc: 所注入bean的ID
(1)将字面量注入到属性中
新的BlankDisc类如下
public class BlankDisc implements CompactDisc{
private String title;
private String artist;
private List<String> tracks;
public void setTitel(String title){
this.title = title;
}
public void setArtist(String artist){
this.artist= artist;
}
public void setTracks(List<String> tracks){
this.tracks= tracks;
}
public void play(){
....
}
}
使用property元素的value属性实现装配
<bean id="compactDisc"
class="soundsystem.BlankDisc">
<property name="title" value="Sgt.peper's loney hearts club" />
<property name="artist" value="The Beatles" />
<property name="tracks">
<list>
<value>Sgt.peper's loney hearts club</value>
<value>loney hearts club</value>
<value>hearts club</value>
<value>club hearts</value>
...
</list>
</property>
另一种可选方案就是 用p-命名空间的属性完成
<bean id="compactDisc"
class="soundsystem.BlankDisc"
p:title="Sgt.peper's loney hearts club"
p:artist="The Beatles">
<property name="tracks">
<list>
<value>Sgt.peper's loney hearts club</value>
<value>loney hearts club</value>
<value>hearts club</value>
<value>club hearts</value>
...
</list>
</property>
但是,注意,不能用p-空间命名来装配集合,可以使用Spring util -命名空间的一些功能来简化BlankDisc bean
首先,在XML中声明utli-命名空间及其模式
<?xml version="1.0" encoding="UTF-8">
<beans xmlns="http://........"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://.....''>
<!-- configuration details go here -->
</beans>
util-命名空间所提供的功能之一就是<util:list>元素,它会创建一个列表的bean.
<util:list id="trackList">
<value>Sgt.peper's loney hearts club</value>
<value>loney hearts club</value>
<value>hearts club</value>
<value>club hearts</value>
</util:lsit>
现在,我们能像使用其他的bean一样,把这个列表的bean注入到BlankDisc bean的tracks属性中
<bean id="compactDisc"
class = "soundsystem.BlankDisc"
p:title="Sgt.pepers lonely hearts"
p:artist="The Beatles"
p:tracks-ref="trackList">
Spring util-命名空间的元素
<util:constant> 引用某个类型的public static域,并将其暴露给bean
<util:list> 创建一个java.util.List类型的bean,其中包含值或引用
<util:map>创建一个java.util.Map类型的bean,其中包含值或引用
<util:properties>创建一个java.util.Properties类型的bean
<util:property-path> 引用一个bean的属性(或内嵌属性),并将其暴露为bean
<util:set>创建一个java.util.Set类型的bean,其中包含值或引用
网友评论