Spring实战第二章学习笔记————装配Bean

创建应用对象之间协作关系的行为通常称为装配(wiring)。这也是依赖注入(DI)的本质。

Spring配置的可选方案

当描述bean如何被装配时,Spring具有非常大的灵活性,它提供了三种主要的装配机制:

  • 在XML中进行显示装配。
  • 在Java中进行显示装配。
  • 隐式的bean发现机制和自动装配。

在这本书中作者建议尽可能使用自动配置的机制。显示配置越少越好。而当你必须要显示配置bean时(比如有些代码不是你维护的,而你需要为这些代码装配bean的时候),推荐使用类型安全且比XML更强大的JavaConfig。

自动化装配bean

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

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

创建可发现的bean

为了阐述组件扫描和装配。我们需要创建几个bean,它们代表了一个音乐系统的组件。首先我们在Java中定义CD的概念。

  1. package com.wbw.soundsystem;
  2. interface CompactDisc {
  3. void play();
  4. }

CompactDisc的具体内容并不重要重要的是它被定义为一个接口。作为接口他定义了CD播放器对CD所能进行的操作。然后我们需要对CompactDisc进行实现。

  1. package com.wbw.soundsystem;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class SgtPeppers implements CompactDisc {
  5. private String title = "Sgt. Pepper's Lonely Hearts Club Band";
  6. private String artist = "The Beatles";
  7. public void play() {
  8. System.out.println("Playing " + title + " by " + artist);
  9. }
  10. }

我们不要了解这个类的具体内容没需要注意的是@compontent。这个简单的注解表明该类会作为组件类,并告知Spring要为这个类创建bean。没有必要显示配置SgtPeppersbean。但组件扫描默认是不启用的。所以我们需要显式配置一下Spring,从而命令他去寻找有@Component注解的类。

  1. package com.wbw.soundsystem;
  2. import org.springframework.context.annotation.ComponentScan;
  3. import org.springframework.context.annotation.Configuration;
  4. @Configuration
  5. @ComponentScan
  6. public class CDPlayerConfig {
  7. }

@ComponentScan注解可以在Spring中开启组件扫描。@Configuration可理解为用spring的时候xml里面的标签。当然也可以用XML来启用组件扫描。这里就不详述了。此时我们创建了两个类,就能对功能进行一番尝试了。为了测试组件扫描的功能,我们创建一个JUnit测试,它会创建Spring上下文,并判断CompactDisc是不是真的创建出来。代码如下:

  1. package com.wbw.soundsystem;
  2. import static org.junit.Assert.assertNotNull;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.test.context.ContextConfiguration;
  7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  8. @RunWith(SpringJUnit4ClassRunner.class)
  9. @ContextConfiguration(classes=CDPlayerConfig.class)
  10. public class CDPlayerTest {
  11. @Autowired
  12. private CompactDisc cd;
  13. @Test
  14. public void cdShouldNotBeNull() {
  15. assertNotNull(cd);
  16. }
  17. }

运行测试,测试通过,说明@Autowired注解起作用了:自动将扫描机制创建的CompactDisc类型的bean注入到SoundSystemTest这个bean中。

为组件扫描的bean命名

在Spring上下文中,每个bean都有自己的ID。在前面的例子中, 尽管我们没有明确地为SgtPeppersbean设置ID,但Spring会根据类 名为其指定一个ID。具体来讲,这个bean所给定的ID 为sgtPeppers,也就是将类名的第一个字母变为小写。 

如果你需要给某个类对应的bean一个特别的名字,则可以给@Component注解传入指定的参数,例如:

  1. @Component("lonelyHeartsClub")
  2. public class SgtPeppers implements CompactDisc {
  3. ...
  4. }

设置组件扫描的基础包

我们没有给@ComponentScan设置任何属性,按照默认规则,它会以配置类所在的包作为基础包(base package)来扫描组件。但是当我们需要扫描其他包时,又该怎么做呢?

为了满足上面提到的需求,我们只需要为@ComponentScan的value属性指定包的名称即可:

  1. //一、直接设置
  2. @Configuration
  3. @ComponentScan("soundsystem")
  4. public class CDPlayerConfig{}
  5. //二、更加清晰表达设置的是基础包,使用basePackages属性
  6. @Configuration
  7. @ComponentScan(basePackages = "soundsystem")
  8. public class CDPlayerConfig{}
  9. //三、设置多个基础包,将basePackages属性设置为一个数组即可
  10. @Configuration
  11. @ComponentScan(basePackages = {"soundsystem", "video"})
  12. public class CDPlayerConfig{}

通过Java代码装配Bean

在进行显式配置时,JavaConfig是更好的方案,因为它更强大且对重构友好。因为它就是Java代码。同时JavaConig与其他的Java代码又有所区别。它是配置代码。意味着它不包含任何事物逻辑。不适必须的,但通常会把JavaConfig放到单独的包中。

创建配置类

  1. import org.springframework.context.annotation.Configuration;
  2. @Configuration
  3. public class CDPlayerConfig {
  4. }

创建JavaConfig的关键在于为其添加@Configuration注解,这个注解表明这个类是一个配置类。

而移除了@ComponentScan注解此时的CDPlayerConfig已经没有作用了。因此接下来就要使用JavaConfig装配CDPlayer和CompactDisc。

声明简单的bean

要在JavaConfig中声明bean,我们需要编写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加@Bean注解。bean的ID默认会和方法名一样,如果想取其他ID可以用bean的name属性:

  1. @Bean
  2. public CompactDisc sgtPeppers(){
  3. return new SgtPeppers();
  4. }
  5. //添加name属性
  6. @Bean(name = "lonelyHeartClubBand")
  7. public CompactDisc sgtPeppers(){
  8. return new SgtPeppers();
  9. }

不管你用什么bean命名,bean的声明都非常简单。这个方法只要我们最后产生CompactDisc实例即可。

借助JavaConfig实现注入

在JavaConfig中装配bean的最简单方式就是引用创建bean的方法。代码如下:

  1. @Bean
  2. public CDPlayer cdPlay(){
  3. return new CDPlayer(sgtPeppers());
  4. }
  5. @Bean
  6. public CDPlayer anotherCDPlay(){
  7. return new CDPlayer(sgtPeppers());
  8. }

cdPlayer()的方法体与sgtPeppers()稍微有些区别。在这里并没有使用默认的构造器构建实例,而是调用了需要传入CompactDisc对象的构造器来创建CDPlayer实例。看起来,CompactDisc是通过调用sgtPeppers()得到的,但情况并非完全如此。因为sgtPeppers()方法上添加了@Bean注解,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用

默认情况下,Spring中的bean都是单例的,我们并没有必要为第二个CDPlayer bean创建完全相同的SgtPeppers实例。所以,Spring会拦截对sgtPeppers()的调用并确保返回的是Spring所创建的bean,也就是Spring本身在调用sgtPeppers()时所创建的CompactDiscbean。因此,两个CDPlayer bean会得到相同的SgtPeppers实例。

小结

有关XML和混合配置的部分暂时先不详述,今天就先写这么多了。

#Spring实战第二章学习笔记————装配Bean的更多相关文章

  1. Spring实战第一章学习笔记

    Spring实战第一章学习笔记 Java开发的简化 为了降低Java开发的复杂性,Spring采取了以下四种策略: 基于POJO的轻量级和最小侵入性编程: 通过依赖注入和面向接口实现松耦合: 基于切面 ...

  2. AS开发实战第二章学习笔记——其他

    第二章学习笔记(1.19-1.22)像素Android支持的像素单位主要有px(像素).in(英寸).mm(毫米).pt(磅,1/72英寸).dp(与设备无关的显示单位).dip(就是dp).sp(用 ...

  3. Spring实战第九章学习笔记————保护Web应用

    保护Web应用 在这一章我们将使用切面技术来探索保护应用程序的方式.不过我们不必自己开发这些切面----我们将使用Spring Security,一种基于Spring AOP和Servlet规范的Fi ...

  4. 聊天室或文字直播间的效果(AS开发实战第二章学习笔记)

    聊天室或文字直播间的效果即是新的文字消息总是加入窗口末尾,同时窗口内部的文本整体向上滚动,窗口的大小.位置保持不变聊天室用到的属性与方法说明gravity 指定文本的对齐方式,取值left|botto ...

  5. TextView的跑马灯效果(AS开发实战第二章学习笔记)

    TextView的跑马灯效果跑马灯用到的属性与方法说明singleLine 指定文本是否单行显示ellipsize 指定文本超出范围后的省略方式focusable 指定是否获得焦点,跑马灯效果要求设置 ...

  6. Android Studio图形基础(AS开发实战第二章学习笔记)

    图形基础 一.drawable 在代码中引用drawable文件可分为两种情况 (1)使用setBackgroundResource和setImageResource方法,可直接在参数中指定drawa ...

  7. Spring实战第八章学习笔记————使用Spring Web Flow

    Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...

  8. Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥

    1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...

  9. Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-2-driver

    1>使用的driver 1〉generic 使用带有SSH的现有VM/主机创建机器. 如果你使用的是机器不直接支持的provider,或者希望导入现有主机以允许Docker Machine进行管 ...

随机推荐

  1. 远程桌面连接(连接服务器)报错Oracle修正

    解决方案: 开始——运行——gpedit.msc——计算机配置——管理模版——系统——凭据分配——加密oracle修正——易受攻击 ok

  2. 【luogu P1314 聪明的质监员】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1314 二分答案 但是计算区间贡献的时候 直接暴力会挂 前缀和加速 #include <cstdio&g ...

  3. 【luogu P3390 矩阵快速幂】 模板

    题目链接:https://www.luogu.org/problemnew/show/P3390 首先要明白矩阵乘法是什么 对于矩阵A m*p  与  B p*n 的矩阵 得到C m*n 的矩阵 矩阵 ...

  4. redis的事务、主从复制、持久化

    redis事务 和其它数据库一样,Redis作为NoSQL数据库也同样提供了事务机制.在Redis中, MULTI/EXEC/DISCARD/WATCH这四个命令是我们实现事务的基石.Redis中事务 ...

  5. data-ng-disabled指令

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  6. mysql substring_index()查询某个字符中以某个分割符分割后的值

    substring_index(某个字段,以其分割,第几个分割点之前的值); +---------------------------------------------------------+ | ...

  7. c/c++面试----c工程开发之头文件

    多数c语言的初学者对c工程开发过程各个阶段的作用理解不到位,而这方面的的知识又是实际开发过程中经常用到的技能点,所以就成为面试考察中一个重要的考察方面.例如:头文件的作用.头文件的内容:链接的作用和意 ...

  8. C++ vector用法积累

    1. vector的初始化 2. vector基本操作 2.1 vector属性 size resize 2.2 vector操作 插入 在最后插入一个元素 push_back() 删除 在最后删除一 ...

  9. BZOj1261: [SCOI2006]zh_tree(dp)

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 400  Solved: 272[Submit][Status][Discuss] Descriptio ...

  10. nignx 配置服务集群

    前言:这里只是简单介绍Nginx简单APP Server集群的搭建和设置发向代理. 后续有时间我会陆续加上Nginx的基础知识.三种负载均衡的策略设置.实现算法的介绍.(最后如果有测试环境,再模拟Ng ...