Spring最基础的特性就是创建bean、管理bean之间的依赖关系。下面通过具体实例演示该如何装配我们应用中的bean。

Spring提供了三种主要的装配机制

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

三种装配方式可依据个人喜好选择使用,无限制。不过应尽可能地使用自动转配机制,因为可以少一大推的配置。在你必须要使用显示配置时,比如要装配一些第三方的bean对象是,可以使用显示的配置。推荐使用类型安全且比xml更加强大的JavaConfig。

自动装配bean

1、创建bean并添加@Component注解

spring通过面向接口编程实现松耦合,因此平时在开发时要养成先创建接口,然后再实现类的习惯。

此处先创建一个CentralProcessUnit接口

public interface CentralProcessUnit {
void compute();
}

然后创建一个具体的实现类HisiCentralProcessUnit:

@Component
public class HisiCentralProcessUnit implements CentralProcessUnit{
public void compute() {
System.out.println("海思芯片,计算。。。。。");
}
}

可以看到,在该类上有一个注解@Component,表明该类是一个组件,spring在扫描的时候会自动创建该类的对象。

当然了,只添加这个注解是不够的。

2、开启组件扫描功能

为了能完成spring 的自动装配功能,除了在需要创建bean的类上添加@Component注解之外,还需要开启组件扫描功能。spring的组件扫描功能默认是关闭的。

开启组件扫描有两种方式:

  • JavaConfig配置方式
  • xml配置方式

Java配置方式

@Configuration
@ComponentScan
public class ScanConfig {
}

XML方式,在spring配置文件中增加如下这段就好:

<context:component-scan base-package="com.herp"/>

3、新建测试类,验证bean是否注入

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ScanConfig.class)
public class AutoWiredBeanTest { @Autowired
private CentralProcessUnit cpu; @Test
public void testNotBeanNull(){
Assert.assertNotNull(cpu);
}
}

在该测试类中使用了@Autowired注解将扫描创建的bean对象注入到此测试类中。

通过上面的三个步骤我们可以看到,我们并没有使用new对象的方式,只是使用了一些spring的注解,spring便帮我们自动完成了对象的创建,并将其注入到了测试类中。

同样地,我们也可以在bean对象之间完成自动装配。我们再创建一个手机对象,然后将cpu芯片对象装配到手机对象中。

创建手机接口和实现类:

@Component
public class HuaweiPhone implements IPhone{ @Autowired
private CentralProcessUnit cpu; public void compute() {
cpu.compute();
}
}

在HuaweiPhone 对象中自动装配CentralProcessUnit的实例。

这里值得注意的是CentralProcessUnit是接口,如果有两个CentralProcessUnit实例,使用自动装配便会产生歧义性,因为spring容器不知道该装配哪个bean了。

使用JavaConfig的显式配置

使用JavaConfig完成bean装配其实就是使用Java代码加spring的注解完成bean的配置、依赖的配置信息。

举例来说明:

本示例中,我们使用JavaConfig的方式完成CentralProcessUnit及IPhone实例的装配。

1、去掉HisiCentralProcessUnit 类上的@Component注解

public class HisiCentralProcessUnit implements CentralProcessUnit {
public void compute() {
System.out.println("海思芯片,计算。。。。。");
}
}

2、去掉ScanConfig中的@ComponentScan注解,只留下@Configuration注解,表示这是一个配置类。然后编写产生HisiCentralProcessUnit bean的方法,并使用@Bean注解标注。

@Configuration
public class ScanConfig {
@Bean
public CentralProcessUnit hisiCentralProcessUnit(){
return new HisiCentralProcessUnit();
}
}

3、如此便完成了最简单的bean的装配了。测试一下:

public class JavaConfigWiredBeanTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanConfig.class);
HisiCentralProcessUnit cpu = applicationContext.getBean("hisiCentralProcessUnit", HisiCentralProcessUnit.class);
cpu.compute();
}
}

输出:

海思芯片,计算。。。。。

可以看到完成了bean的转配。

4、同样地,我们去掉HuaweiPhone上的@Component注解,并提供一个带参数的构造器,注意参数类型是CentralProcessUnit(接口),而非具体实现类,具体类接下来我们会使用JavaConfig的配置的方式注入。

public class HuaweiPhone implements IPhone {

    private CentralProcessUnit cpu;

    // 构造器注入
public HuaweiPhone(CentralProcessUnit cpu){
this.cpu = cpu;
} public void compute() {
System.out.println("华为手机+++");
cpu.compute();
}
}

5、我们在ScanConfig中加入huaweiPhone的配置,并注入hisiCentralProcessUnit实例。

@Configuration
public class ScanConfig { @Bean
public CentralProcessUnit hisiCentralProcessUnit(){
return new HisiCentralProcessUnit();
} @Bean
public IPhone huaweiPhone(){
return new HuaweiPhone(hisiCentralProcessUnit());
}
}

6、验证依赖注入是否成功。使用AnnotationConfigApplicationContext容器类获取装配好的bean。

public class JavaConfigWiredBeanTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanConfig.class);
// 依赖注入示例测试
IPhone huaweiPhone = applicationContext.getBean("huaweiPhone",HuaweiPhone.class);
huaweiPhone.compute();
}
}

输出结果:

华为手机+++
海思芯片,计算。。。。。

使用JavaConfig配置bean和依赖关系,具有极大的灵活性,我们只需要在带有@Bean注解的方法上最终产生一个bean实例即可,具体bean实例的产生逻辑只受Java语言自身的限制。

比如我们可以这样配置一个bean:

    @Bean
public CentralProcessUnit randomCentralProcessUnit(){
int num = (int) Math.floor(Math.random() * 2);
if(num == 0){
return new HisiCentralProcessUnit();
}else {
return new GaoTongCentralProcessUnit();
}
}

这个CentralProcessUnit 是随机生成HisiCentralProcessUnit芯片或者是GaoTongCentralProcessUnit芯片。

使用XML完成bean装配和DI

XML配置的方式是spring最早采用的配置bean、bean之间的依赖关系的方式。

使用XML配置其实很简单,使用元素声明一个bean即可。

1、最简单的bean配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="centralProcessUnit" class="com.herp.beanwired.xmlwired.GaoTongCentralProcessUnit"/>
</beans>

这样当spring发现元素时,会调用GaoTongCentralProcessUnit的默认构造器来创建bean。

2、使用构造器依赖注入bean

    <bean id="iphone" class="com.herp.beanwired.xmlwired.HuaweiPhone">
<constructor-arg ref="centralProcessUnit"/>
</bean>

测试类

public class XMLConfigWiredBeanTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-beans.xml");
IPhone phone = context.getBean("iphone",IPhone.class);
phone.compute();
}
}

输出:

华为手机+++
高通芯片,计算。。。。

3、使用属性注入bean依赖

    <bean id="centralProcessUnit_hw" class="com.herp.beanwired.xmlwired.HisiCentralProcessUnit"/>
<bean id="anotherPhone" class="com.herp.beanwired.xmlwired.HuaweiPhone">
<property name="centralProcessUnit" ref="centralProcessUnit_hw"/>
</bean>

同时,需要在HuaweiPhone类中提供setter方法

    public void setCentralProcessUnit(CentralProcessUnit centralProcessUnit){
this.centralProcessUnit = centralProcessUnit;
}

测试类,替换成获取id为anotherPhone 的bean对象:

public class XMLConfigWiredBeanTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-beans.xml");
IPhone phone = context.getBean("anotherPhone",IPhone.class);
phone.compute();
}
}

输出如下:

华为手机+++
海思芯片,计算。。。。。

总结

本节主要总结了spring装配bean和依赖注入的三种方式:组件扫描和自动装配、JavaConfig注解配置方式、XML配置方式。平时开发中优先使用组件扫描和spring自动发现的机制装配bean,这样可以省去大量配置类或配置文件,其次是使用JavaConfig的方式,一方面,它是类型安全的,另外在配置bean时提供了更大的灵活性。最后选用XML配置文件的方式装配bean。

【10分钟学Spring】:(二)一文搞懂spring依赖注入(DI)的更多相关文章

  1. 五分钟学Java:一篇文章搞懂spring和springMVC

    原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 什么是Spring,为什么你要学习spring? 你第一次接触spring框架是在什么时候?相信很多人和我一样,第一次了 ...

  2. 一文搞懂spring的常用注解

    spring传统做法是使用xml文件对bean进行注入和配置.通过使用spring提供的注解,可以极大的降低配置xml文件的繁琐.本文将介绍常用的注解. 一@Autowired Autowired意为 ...

  3. spring中的控制反转IoC和依赖注入DI

    原文:http://blog.163.com/xianghuxian@126/blog/static/50639037200721345218382/ IoC(Inversion of Control ...

  4. Spring_01 spring容器、控制反转(IOC)、依赖注入(DI)

    目录 1 什么是spring框架 2 spring框架的特点 3 spring容器 3.1 什么是spring容器 3.2 spring容器创建对象的编程步骤 3.4 spring容器创建对象的方式 ...

  5. 趣学Spring:一文搞懂Aware、异步编程、计划任务

    你好呀,我是沉默王二,一个和黄家驹一样身高,刘德华一样颜值的程序员(不信围观朋友圈呗).从 2 位偶像的年纪上,你就可以断定我的码龄至少在 10 年以上,但实话实说,我一直坚信自己只有 18 岁,因为 ...

  6. 一文搞懂│php 中的 DI 依赖注入

    目录 什么是 DI / 依赖注入 依赖注入出现的原因 简单的依赖注入 高阶的依赖注入 依赖注入的应用 依赖注入高阶优化 什么是 DI / 依赖注入 依赖注入DI 其实本质上是指对类的依赖通过构造器完成 ...

  7. 三文搞懂学会Docker容器技术(中)

    接着上面一篇:三文搞懂学会Docker容器技术(上) 6,Docker容器 6.1 创建并启动容器 docker run [OPTIONS] IMAGE [COMMAND] [ARG...] --na ...

  8. Web端即时通讯基础知识补课:一文搞懂跨域的所有问题!

    本文原作者: Wizey,作者博客:http://wenshixin.gitee.io,即时通讯网收录时有改动,感谢原作者的无私分享. 1.引言 典型的Web端即时通讯技术应用场景,主要有以下两种形式 ...

  9. 三文搞懂学会Docker容器技术(下)

    接着上面一篇:三文搞懂学会Docker容器技术(上) 三文搞懂学会Docker容器技术(中) 7,Docker容器目录挂载 7.1 简介 容器目录挂载: 我们可以在创建容器的时候,将宿主机的目录与容器 ...

随机推荐

  1. Spring IOC容器装配Bean_基于XML配置方式

    开发所需jar包 实例化Bean的四种方式 1.无参数构造器 (最常用) <?xml version="1.0" encoding="UTF-8"?> ...

  2. 2019-2020-11 20199304 《Linux内核原理与分析》 第十二周作业

    ShellShock攻击实验 一.实验简介 2014年9月24日,Bash中发现了一个严重漏洞shellshock,该漏洞可用于许多系统,并且既可以远程也可以在本地触发 二.预备知识 1.shells ...

  3. Flink入门(二)——Flink架构介绍

    1.基本组件栈 了解Spark的朋友会发现Flink的架构和Spark是非常类似的,在整个软件架构体系中,同样遵循着分层的架构设计理念,在降低系统耦合度的同时,也为上层用户构建Flink应用提供了丰富 ...

  4. 一条数据的HBase之旅,简明HBase入门教程3:适用场景

    [摘要] 这篇文章继HBase数据模型之后,介绍HBase的适用场景,以及与一些关键场景有关的周边技术生态,最后给出了本文的示例数据 华为云上的NoSQL数据库服务CloudTable,基于Apach ...

  5. mq解决分布式事物问题

    今天只看看原理,下一节看项目怎么集成mq进行解决分布式事物. 1.什么情况下会使用到分布式事物? 举例说明:现有一个支付系统,因为项目使用的是微服务框架,有订单模块和支付模块两个模块.生产者进行订单的 ...

  6. 整合多个maven工程时Spring配置加载JDBC问题

    问题叙述: 两个工程都通过JDBC访问mysql数据库,各自运行OK, 但合并成一个maven工程后,发现前一个工程访问数据库异常,貌似拿不到自己的DAO. 解决办法: 发现这两个工程的xml配置中, ...

  7. MySQL必知必会(数据分组,Group by和Having子句, Select子句的顺序)

    SELECT vend_id, COUNT(*) AS num_prods FROM products #GROUP BY子句可以包含任意数目的列,多行NULL值将分为一组 GROUP BY vend ...

  8. [TimLinux] CSS float和position详解

    1.1. 定义 摘自w3school:float 属性定义元素在哪个方向浮动.以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动.浮动元素会生成一个块级框,而不论它 ...

  9. HDU2482-Transit search(地图还原+SPFA)

    Henry decides to develop a web site, which will provide the service of transit search. But he can on ...

  10. Oracle - 通过dg,完成单实例到rac的迁移

    一.概述 本文将介绍如何给单实例搭建一个rac dg,以及如何对其进行角色转换,完成从单实例到rac的迁移.预先具备的知识(rac搭建,单实例-单实例dg搭建) 二.实验环境介绍 主库(已有数据库实例 ...