Spring实战笔记——装配Bean

上一章主要讲述了Spring的主要设计思路。接下来的章节将讲解Spring各种设计思路的具体实现。本章和下一章重点讲解Bean的装配方式,本章将重点介绍Bean的基本装配方法。

本章内容:

  1. 声明bean
  2. 构造器注入和Setter
  3. 装配bean
  4. 控制bean的创建和销毁

一个软件的作用是实现某种功能,当然功能也有简单和复杂之分。你可以将一个具有复杂功能的应用程序看作一个功能来实现——写一个很大很大很大的源代码,也可以将这个具有复杂功能的程序进行拆分,然后由一些简单的程序(组件)通过协作的方式来实现复杂的功能。而软件的模块化设计几乎是现代所有程序设计都遵循的规则。
Spring也是遵循这个思路的。Spring已经完成了很多底层的功能,程序员只需要按照功能的需求写出相应的应用组件,再通过容器把需要相互协作的组件进行管理。在java中,一个对象可以看作是一个组件,Spring创建对象之间协作关系的行为称为装配,者也是DI的本质

1, Spring配置bean的方案

spring有三种基本的装配bean机制:

  1. 在XML中进行显示配置
  2. 在Java中进行显示配置
  3. 隐式的bean发现机制和自动装配

可以只采用一种方式(自己喜欢的)来装配bean,也可以freestyle,将三种装配方式混合使用。

Spring实战作者推荐的装配策略:尽可能使用自动配置的机制,这样显示的配置最少。当必须显示配置bean的时候,优先使用类型安全并且比XML更加强大的JavaConfig。最后当想要使用便利的XML命名空间,并且在JavaConfig中没有同样的实现时,应该使用XML。

1.1,自动化装配bean

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

  1. 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。
  2. 自动装配(autowiring):Spring自动满足bean之间的依赖关系。

首先创建一个可以被发现的bean。
以CD机为例(参考书本):

package com.example.chr1s;

public interface CompactDisc {
    void play();
}

这里定义了一个接口,CD可以存放音乐,所有的CD都是能播放的,所以在接口里定义了一个play()方法,但是CD里面存储的具体是什么则应该由实现该接口的类来表示。

接着创建一个实现这个接口的类

package com.example.chr1s;
import org.springframework.stereotype.Component;

@Component
public class SgtPeppers implements CompactDisc {
    private String title "Sgt. Pepper's Lonely Hearts Club Band";
    private String artist = "The Beatles";

    @Override
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
    }
}

@Component注解表明该类会作为组件类,并且告知Spring要为这个类创建bean。

组件扫描默认是关闭的,需要显示配置Spring,从而命令它去寻找带有@Component注解的类。

package com.example.config;
import org.springframework.context.annotation.componentScan;
import org.springframe.context.annotation.Con;

@Configuration
@ComponentScan("com.example.chr1s")
public class CDPlayerConfig {

}

@Configuration注解表明CDplayerConfig 是一个Java配置类,@ComponentScan能够在Spring中启动组件扫描
@ComponentScan注解如果没有参数,则默认在当前包中扫描bean。给定参数后,在参数所标定的位置进行扫描。

测试组件扫描能够发现CompactDisc

package com.example.chr1s;

import com.example.config.CDPlayerConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertNotNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {

    @Autowired
    private CompactDisc cd;

    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(cd);
    }
}

单元测试以后再说,这里重点说明Spring相关的东西。SpringJUnit4ClassRunner可以在测试开始的时候自动创建Spring的应用上下文,@ContextConfiguretion会告诉它需要的配置文件。@Autowiring注解表示自动装配bean。

关于bean的一些额外配置

  1. 为组件扫描的bean命名:@Component(“beanID”)
  2. 使用Java注入规范的@Named注解为bean设置ID:@Named(“beanID”)
  3. 为自动扫描设置多个基础包:@ComponentScan(basePackages={“package1”, “package2”, “package3”})
  4. 如果要求自动扫描实现类型安全:@ComponentScan(basePackageClasses={interface1.class, interface2.class}),对应的类所在的包将作为扫描组件的基础包

    以上的代码实现了bean的最基本的装配,这些bean彼此之间还没有依赖关系。在实际的程序设计中,bean之间是相互依赖的,需要将扫描得到的bean和它们的依赖装配到一起。

自动装配是为了让Spring自动满足bean依赖的一种方法。

package com.example.chr1s;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements CompactDisc {

    private CompactDisc cd;

    @Autowired
    public CDPlayer(CompactDisc cd) {
        this.cd = cd;
    }

    public void play() {
        cd.play();
    }
}

一个CDPlayer能正常播放需要有插入CD,也就是说CDPlayer是依赖CompactDisc的。在上面的代码中,@Autowried用于构造器上。@Autowried注解还能用在属性的Setter方法上。在Spring初始化bean之后,它会尽可能去满足bean的依赖。

Spring装配bean的异常处理方式:

  1. 假如有且只有一个bean匹配依赖需求,那么这个bean就会被装配进来。
  2. 如果没有匹配的bean,Spring在应用上下文创建的时候会抛出一个异常。如果将@autowried的require属性设置成false,会抑制这个异常,但是在接下来的代码中,如果对bean的引用没有进行null检查的话,这个未装配状态的属性则由可能出现NullPointerException。
  3. 如果多个bean都能满足依赖关系的话,Spring也会抛出异常。

验证自动装配:

package com.example.chr1s;

import com.example.config.CDPlayerConfig;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {

    @Rule
    public final StandardOutputStreamLog log = new StandardOutputStreamLog();

    @Autowired
    private CompactDisc cd;

    @Autowired
    private CDPlayer player;

    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(cd);
    }

    @Test
    public void play() {
        player.play();
        assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\r\n", log.getLog());
    }
}

通过Java代码显示装配bean

自动化装配不是万能的,比如自动化装配就无法将第三方库中的组件装配到自己的应用中。显示的装配方式有两种:

  1. 基于Java
  2. 基于XML

基于Java的显示装配

@Bean注解会告诉Spring接下来编写的方法将返回一个对象,该对象会注册为Spring应用上下文中的bean。默认情况下,bean的ID与带有@Bean注解的方法名是一样的,也可以通过name属性进行修改:

@Bean(name="beanID")
public CompactDisc sgtPeppers() {
    return new SgtPeppers();
}

通过Java代码实现DI-构造器注入

@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
    return new CDPlayer(compactDisc)
}

通过Java代码实现DI-Setter方法注入

@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
    CDPlayer cdPlayer = new CDPlayer();
    cdPlayer.setCompactDisc(compactDisc);
    return cdPlayer;
}

通过XML装配Bean

XML设置有几个重要的节点

  1. <beans>节点是所有bean的根节点
  2. <bean>节点对应Spring中的一个bean,它有几个重要的属性:1,id属性,对应JavaConfig中的name属性;class属性表明bean所属的类
  3. <constructor-arg>确定bean的构造器参数。它是<bean>节点的子节点,也有几个重要的属性:1,value属性,表征字面值常量参数;2,ref属性,表征引用类型参数。constructor-arg节点还有一些子节点,如list, map等,用于定义集合来作为构造器参数。这些属性是实现构造器注入的基础。
  4. <property>节点用于实现Setter注入。 与<constructor-arg>类似,它也有几个重要属性:1,name,表征引用的变量;2,value表征具体的值;list,map等子节点用法与第三点中的一样。

XML的配置方法的示例代码本文不再描述

混合配置

1,在JavaConfig中导入XML配置
在JavaConfig中通过@Import注解导入其它JavaConfig类中的配置,通过@ImportResource注解导入XML配置

2,在XML中导入JavaConfig
在XML中使用<import>元素导入XML配置文件 ,如<import resource="spring-config.xml">,通过在<bean>中引入JavaConfig名称能导入JavaConfig文件, 如<bean class="com.example.config.CDPlayerConfig">。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值