spring实战第二章:装配bean

一、装配的3种方式(3种方式可以交叉使用)

1、在XML中进行显式配置

2、在Java中进行显式配置

3、隐式的bean发现机制和自动装配(推荐)

二、自动装配bean(方式1)

1、声明bean

使用@Component注解定义bean

@Component("name") 将类定义为组件并命名,可以不命名,默认组件id为将类名第一个字母改为小写。

@Named("name") 大多数情况下与@Component("name")相同,注解来源于 Java 依赖注入规范。

@Component
public class SgtPeppers implements CompactDisc{
    private String title = "title";
    private String artist = "artist";
    public void play(){
        System.out.print("Playing "+title+" by "+ artist);
    }
}

2、开启组件扫描

寻找带有@Component注解的类,为其创建bean

方式1:java

@Configuration
@ComponentScan
public class CDPlayerConfig {
//这里没有任何显式配置
//在接下来的java配置这里将添加配置关系
}

a、@Configuration:表明这是一个配置类

b、@ComponentScan:启用组件扫描,默认扫描与配置类相同的包及子包,查找带有@Component注解的类

如果需要设置自定义扫描不同的包:

(1)@ComponentScan(“com.xxx.xxx”) :即给value属性赋值

(2)@ComponentScan(basePackages=“com.xxx.xxx”) 

         @ComponentScan(basePackages={“com.a.xxx”,"com.b.xxx"})  :复数形式    

(3)前2种类型不安全(重构时基础包可能发生变更)

          @ComponentScan(basePackageClasses={a.class,b.class})  :这些类所在的包将会作为组件扫描基础包;         

方式2:xml

在xml中配置<context:component-scan base-package=”com.xxx.xx“>

 

3、装配bean

@Autowired:Sping特有注解,根据类型匹配,可以装配在类的任意方法上;

 @Inject:来源于Java依赖注入规范,和@Autowired差别很小;

匹配规则:

(1)如果只有一个bean匹配,装配这个bean

(2)如果没有匹配的bean,抛异常(加required=false不会抛)

(3)多个bean满足,抛异常

@Component
public class CDPlayer implements MediaPlayer {
    private CompactDisc cd;

    // 表明当spring创建CDPlayer bean时会通过构造器来进行实例化
    // 并且会传入一个可设置给CompactDisc的bean
    // 构造方法
    @Autowired
    public CDPlayer(CompactDisc cd){
        this.cd = cd;
    }

    // setter方法
    @Autowired(required = false)
    public void setCompactDisc(CompactDisc cd){
        this.cd = cd;
    }

    // 普通方法   
    @Autowired
    public void insertDisc(CompactDisc cd){ // 什么时候创建bean呢??
        this.cd = cd;
    }
}

// 创建CDPlayer bean时自动注入CompactDisc,以上3种方式均可,和方法名无关。无需显式调用

四、通过java代码装配bean-方式2

如果将第三方组件装配到自己应用中,无法通过添加@Component和@Autowired注解,需要使用显式配置:Java和xml;

1、创建配置类:添加@Configuration注解

2、声明bean:使用@Bean注解

@Bean:返回的对象将注册为上下文中的bean,默认bean id与@Bean注解的方法名一样,此处即sgtPeppers;

@Bean(name=“stupid”):重命名id为stupid

(@Bean = @Component + @ComponentScan+@Autowired)

 // 去掉了ComponentScan,不使用组件扫描,使用显式配置创建bean
@Configuration
public class CDPlayerConfig {
    
   @Bean 
   public CompactDisc sgtPeppers() {
        return new SgtPeppers();// 方法体内容可以随意编排,最终返回对象都将作为bean
   }
}

3、装配bean:

 // 去掉了ComponentScan,不适用组件扫描,使用显式配置创建bean
@Configuration
public class CDPlayerConfig {
    
   @Bean 
   public CompactDisc sgtPeppers() {
        return new SgtPeppers();// 方法体内容可以随意编排,最终返回对象都将作为bean
   }

   @Bean
   public CDPlayer cdPlayer() {
   // sgtPeppers()有添加注解@Bean,Spring会拦截所有对它的调用,并返回该方法创建的bean,
      而不是每次对其进行实际调用
        return new CDPlayer(sgtPeppers());
   }
  
   // 当Spring调用cdPlayer()创建CDPlayer bean时会自动装配一个CompactDisc到方法中
   // 这种方式不会要求CompactDisc声明到同一个配置类中,可以通过组件扫描或xml方法都行
   @Bean 
   public CDPlayer cdPlayer(CompactDisc compactDisc) {
        return new CDPlayer(compactDisc);
   }
}

问题:cdPlayer()、sgtPeppers()在什么时候被调用的?自动or手动?   spring容器启动时自动

五、xml装配bean-方式3

1、声明bean

<beans ...>
    <!--class属性:全限定类名,存在风险当实际类名称变更,此处无法验证 -->
    <bean class="com.sankuai.m" /> 
    <!-- 没有明确指定id,默认根据全限定名命名,此处即”com.sankuai.m#0"
         #0用来区分相同类型其他bean,如果另外声明这个类的bean并且没有明确标识,
         自动得到的id将是”com.sankuai.m#1"->
 
    <!--id属性:指定bean名称 -->
    <bean id="t" class="com.sankuai.t" /> 
</beans>

2、装配bean

构造器注入bean引用:

(1)<constructor-arg>元素

<bean id="t" class="com.sankuai.t" >
    <contructor-arg ref = "cc"> <!--cc为其他bean的id -->
</bean>

(2)Spring 3.0引入的c-命名空间

a、xml顶部声明c-命名空间和模式

b、使用

<!--
”c:“ - 命名空间前缀
”cd“:要装配的构造器参数名称,有点鸡肋
”-ref“:代表装配bean的引用 
-->
<bean id="t" class="com.sankuai.t" 
      c:cd-ref = "cc"/> 


<!-- 
 "_0":表示第一个构造器参数
-->
<bean id="t" class="com.sankuai.t" 
      c:_0-ref = "cc"/> 

<!-- 
"_":此处构造器只有一个参数,可以省略索引号 
-->
<bean id="t" class="com.sankuai.t" 
      c:_-ref = "cc"/> 

注入字面量:

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.out.println("xxx"); 
     }
}

装配方式:

<!--使用value,不用ref -->
<bean id="compactDisc" class="soundsystem.BlankDisc">
     <constructor-arg value="lonely hearts club band"/>
     <constructor-arg value="The Beatles"/>
</bean>

<!--去掉了 -ref,使用"_参数名"-->
<bean id="compactDisc" class="soundsystem.BlankDisc"
     c:_title="lonely hearts club band"
     c:_artist="The Beatles"/>
</bean>

<!-- 参数名转换为索引号 -->
<bean id="compactDisc" class="soundsystem.BlankDisc"
     c:_0="lonely hearts club band"
     c:_1="The Beatles"/>
</bean>

<!-- 只有一个参数,省略索引号 -->
<bean id="compactDisc" class="soundsystem.BlankDisc"
     c:_="lonely hearts club band"/>
</bean>

注入集合:

P56页,目前c-命名空间无法装配集合

 

3、设置属性

注入bean引用:

(1)<property> 方式

<!-- 引用id为compactDisc的bean(通过ref属性),将其注入到compactDisc
属性中(通过setCompactDisc方法) -->
<bean id="cdPlayer" class="soundsystem.CDPlayer">
     <property name="compactDisc" ref="compactDisc"/>
</bean>

问题:上面 @Autowired属性的作用是?自动注入compactDisc属性

(2)p-命名空间

a、xml顶部声明

b、使用

<!-- 
"p:":前缀
"compactDisc":属性名
-->
<bean id="cdPlayer" class="soundsystem.CDPlayer"
     p:compactDisc-ref="compactDisc">
</bean>

注入字面量:

(1)<property> 方式

<!-- 相对于引用,将ref改为value-->
<bean id="cdPlayer" class="soundsystem.CDPlayer">
     <property name="compactDisc" value="value xxxx"/>
</bean>

(2)p-命名空间

<bean id="cdPlayer" class="soundsystem.CDPlayer"
     p:title="title value xxx"
     p:artist="artist value xxx">
   <property name="age" value="333" />
</bean>

和构造器一样,注入字面量和引用的区别在于是否带有ref;

其他:使用 JavaConfig 替换 Spring 的 XML 配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值