【10分钟学Spring】:(二)一文搞懂spring依赖注入(DI)

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。

原文地址:https://www.cnblogs.com/happyone/p/11992085.html

时间: 2024-07-31 03:41:49

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

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

原文:http://blog.163.com/[email protected]/blog/static/50639037200721345218382/ IoC(Inversion of Control),这是spring的核心,贯穿始终.所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关 系.这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好.qq 号.电话号.手机号.

一文搞懂 RSA 算法

一文搞懂 RSA 算法 地球上最重要的算法 如果没有 RSA 算法,现在的网络世界毫无安全可言,也不可能有现在的网上交易.上一篇文章 ssh 协议为什么安全 中的 ssh 协议也是基于 RSA 加密算法才能确保通讯是加密的,可靠的. 1976年以前,所有的加密方法都使用对称加密算法:加密和解密使用同一套规则.例如:甲使用密钥 A 加密,将密文传递给乙,乙仍使用密钥 A 解密.如果密钥 A 在甲传递给乙的过程中泄露,或者根据已知的几次密文和明文推导出密钥 A,则甲乙之间的通讯将毫无秘密. 1976

【Data Visual】一文搞懂matplotlib数据可视化

一文搞懂matplotlib数据可视化 作者:白宁超 2017年7月19日09:09:07 摘要:数据可视化主要旨在借助于图形化手段,清晰有效地传达与沟通信息.但是,这并不就意味着数据可视化就一定因为要实现其功能用途而令人感到枯燥乏味,或者是为了看上去绚丽多彩而显得极端复杂.为了有效地传达思想概念,美学形式与功能需要齐头并进,通过直观地传达关键的方面与特征,从而实现对于相当稀疏而又复杂的数据集的深入洞察.然而,设计人员往往并不能很好地把握设计与功能之间的平衡,从而创造出华而不实的数据可视化形式,

一文搞懂蓝绿发布、灰度发布和滚动发布(转)

应用程序升级面临最大挑战是新旧业务切换,将软件从测试的最后阶段带到生产环境,同时要保证系统不间断提供服务. 长期以来,业务升级渐渐形成了几个发布策略:蓝绿发布.灰度发布和滚动发布,目的是尽可能避免因发布导致的流量丢失或服务不可用问题. 一. 蓝绿发布 项目逻辑上分为AB组,在项目系统时,首先把A组从负载均衡中摘除,进行新版本的部署.B组仍然继续提供服务. 当A组升级完毕,负载均衡重新接入A组,再把B组从负载列表中摘除,进行新版本的部署.A组重新提供服务. 最后,B组也升级完成,负载均衡重新接入B

一文搞懂vim复制粘贴

转载自本人独立博客https://liushiming.cn/2020/01/18/copy-and-paste-in-vim/ 概述 复制粘贴是文本编辑最常用的功能,但是在vim中复制粘贴还是有点麻烦的,有一点学习成本.本文总结了使用vim复制粘贴的典型场景和使用方法,希望对读者有帮助. vim内部复制.粘贴.剪切 选择文本 v+光标移动 (按字符选择)高亮选中所要的文本,然后进行各种操作(比如,d表示删除). V (按行选择) v+选中的内容+c 更改选中的文字 复制:y(ank) y 用v

spring(3)------控制反转(IOC)/依赖注入(DI)

一,spring核心概念理解 控制反转: 控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理. 所谓的"控制反转"概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器. 没有控制反转这种模式前,你创建一个对象,在什么地方用,你得单独通过关键字new出来用, 但现在可以不用这样,你把new对象的权利交给spring配置文件,通过配置文件来'new', 就是权利的反转,你以前干的事

浅析Spring IOC、依赖注入(DI)和依赖查找(DL)

为什么要用IOC? 第一:对象的实例化不是一件简单的事情,比如对象的关系比较复杂,依赖关系往往需要程序员去维护,这是一件非常头疼的事. 第二:解耦,由容器去维护具体的对象 第三:托管了类的产生过程,比如我们需要在类的产生过程中做一些处理,最直接的例子就是代理,如果有容器程序可以把这部分过程交给容器,应用程序则无需去关心类是如何完成代理的 控制反转(Inverse of Control) 控制反转即IoC(Incersion of Control),从字面上理解就是控制反转,将对在自身对象中的一个

Spring IOC源代码具体解释之容器依赖注入

Spring IOC源代码具体解释之容器依赖注入 上一篇博客中介绍了IOC容器的初始化.通过源代码分析大致了解了IOC容器初始化的一些知识.先简单回想下上篇的内容 加载bean定义文件的过程.这个过程是通过BeanDefinitionReader来完毕的.当中通过 loadBeanDefinition()来对定义文件进行解析和依据Spring定义的bean规则进行处理 - 其实和Spring定义的bean规则相关的处理是在BeanDefinitionParserDelegate中完毕的,完毕这个

spring 依赖注入(DI)与控制反转(IOC)

Spring目前所拥有的功能非常多,常用的DI和MVC已经是开发中的家常便饭,而且使用Spring来管理其它的框架也是习以为常的事情.Spring在项目中的最大作用就是为了解耦,降低项目整体的耦合度,尽可能做到低耦合.Spring的核心就是IOC和AOP.IOC控制反转创建bean对象,通过DI依赖注入来完成bean对象的数据封装. IOC是一种开发思想,DI是一种开发实现 虽然业界经常提到什么IOC,什么DI,其实都是一个意思,只是IOC是Spring提出的设计开发思想,而DI是代码实现方式.