Spring第三回、sping三种装配Bean方案

sping的配置方案有三种:
  隐式的bean发现机制和自动装配
  在xml中显示配置
  在java中进行显示配置
  尽可能的使用自动装配,显示装配越少越好,如果必须要用显示装配,最好用javaConfig装配。(javaConfig比XML安全)
  xml配置
  优势:集中配置,代码配置分离更加方便管理
  劣势:繁杂,编译期不容易发现错误
javaConfig配置
  优势:代码简洁,
  劣势:国内xml配置方式比较多,不容易被人接受
  
一、自动化装配bean
  @Component:表明这是一个组件,可以用@Named替代
  @ComponentScan:组件扫描
  @Configuration:表明这时一个配置类
  @Autowired:自动装配组件,可以用@Inject替代
  @Named和@Inject都来自java依赖注释规范的,如果想使用这两个注解需要引入依赖:

<!-- java依赖注入文档 -->
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

1、创建组件
  创建4个组件,歌手Singer接口:

/**可以直接用@Component,他会默认给这个bean指定一个id为singer,
*  当然你也可以自己指定id,如@Conponent("singer")如果多个包中有相同名字的类,会不会混淆Bean?bean跟包的存储方式是否相同?
*/
@Component
public interface Singer {
    public void sing();
}

  周杰伦实现Singer,会sing()

@Component
public class ZhouJL implements Singer {
    @Override
    public void sing() {
        System.out.println("周杰伦 is Singing");
    }
}

  播放器Player 接口:

@Component
public interface Player {
    public void play();
}

  CDPlayer播放器实现Player

@Component
public class CDPlayer implements Player{
    @Autowired
    private Singer singer;

    /** 注意: 上面一个@Autowired可以不写,而这个不写会报错。 
     *  很疑惑?我项目中确实恰恰相反,可能需要配置吧?
     */
    @Autowired
    public CDPlayer(Singer singer) {
        this.singer = singer;
    }

    @Override
    public void play() {
        singer.sing();
    }

}

  
2、配置组件

@Configuration
/**
 * 1.用@ComponentScan只会扫描当前包下的组件
 * 2.用@ComponentScan("com.cs.model.stu")会扫面包com.cs.model.stu下的组件,但是不利于代码重构与维护,
 *   当然还可以显示指示:@ComponentScan(basePackages = "com.cs.model.stu")
 *   还可以指定多个包路径:@ComponentScan(basePackages = {"com.cs.model.stu","com.cs.model.ss"})
 * 3.指示类所在包路径:
 *   @ComponentScan(basePackageClasses = Singer.class),他会扫描Singer所在包下的所有组件
 *   @ComponentScan(basePackageClasses = {Singer.class,People.class}),扫描多个类的包路径
 */
@ComponentScan("com.cs.model.stu")
public class SingerConfig {

}

3、测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SingerConfig.class)
public class ZhouJLSingTest {
    @Autowired 
    private Singer singer;

    @Autowired
    private Player player;

    @Test
    public void testSing() {
        assertNotNull(singer);
    }

    /*会不会很疑惑?接口调用其方法结果是调用的实现类的方法*/
    @Test
    public void testPlay() {
        player.play();
    }
}

测试是可以通过的。结果如下:

周杰伦 is Singing

二、使用java装配bean
1、既然要优先使用自动装配,那为什么为什么要用java显示装配呢?
A:假如有时候需要将第三方库中的组件装配到应用中,这个时候没有办法在第三方库中的类上加@component,因此这时需要显示配置bean。

2、为什么显示装配优先使用javaConfig 而不是 xml配置?
A:java更为强大、类型安全且(java语言的她点)对重构友好
  这个很简单,主要是类跟配置文件不一样:
  i.需要装配的类不需要加@Component注解
  ii.配置文件不再使用@ComponentScan,而是使用@Bean

3、代码格式
  Config在一个单独的包中,里面最好只配置bean,不应该有任何的业务逻辑。
  
  使用java装配bean,示例如下:
  类只举一个例子:

//这里无需@Component注解
public interface Player {
    public void play();
}
public class SingConfig {
    //使用@Bean装置bean,给创建的bean赋id使用name属性
    @Bean(name = "singer")
    public Singer singer() {
        return new ZhouJL();
    }

    @Bean(name = "player")
    public Player player() {
    //singer()返回的是Singer的Bean,而不是他的对象的引用:@Bean会拦截所有对他的调用
        return new CDPlayer(singer());
    }    
}

测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = SingerConfig.class)
@ContextConfiguration(classes = SingConfig.class)
public class ZhouJLSingTest {
    @Autowired 
    private Singer singer;

    @Autowired
    private Player player;

    @Test
    public void testSing() {
        assertNotNull(singer);
    }

    @Test
    public void testPlay() {
        player.play();
    }
}

三、使用xml显示装配bean
  建议最好使用前两种来装配bean,学习xml只是为了维护项目中的老旧xml。
  同样,类不需要任何注解,只需要在xml中配置即可,xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context">

    <bean id="singer" class="com.cs.model.stu.ZhouJL"/>

    <!-- <bean id="player" class="com.cs.model.stu.CDPlayer">
        <constructor-arg ref="singer"></constructor-arg>
    </bean>  -->    

    <bean id="player" class="com.cs.model.stu.CDPlayer"
        c:_0-ref="singer"/>
</beans>

  注意:
  如果一个类需要被引用,这个类最好需要定义一个Id。
  用xml定义bean的时候,如果不明确指给定Id,bean会根据类名的全限定名进行命名,例如:

<bean id="singer" class="com.cs.model.stu.ZhouJL"/>

  如果不写id=”singer”,bean Id将会是com.cs.model.stu.ZhouJL#0。而在自动配置、javaConfig配置如下:

//如果使用@Component,bean id 默认为player(类名的首字母小写)
@Component("player")
public interface Player {
    public void play();
}


public class SingConfig {
    //如果不指定name ,则bean id 为方法名。
    @Bean(name = "singer")
    public Singer singer() {
        return new ZhouJL();
    }
}

可以看出差别,如果都不指定bean id,则:
  如果使用@Component,bean id 默认为类名的首字母小写(player)
  用javaConfig,如果不指定name ,则bean id 为方法名
  用xml定义bean的时候,如果不明确指给定Id,bean会根据类名的全限定名进行命名
  测试代码如下:
  

package test;

@RunWith(SpringJUnit4ClassRunner.class)
public class ZhouJLSingTest {
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext("config/sing.xml");

    private Singer singer = annotationConfigApplicationContext.getBean(ZhouJL.class);

    @Test
    public void testSing() {
        assertNotNull(singer);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值