打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Spring入门基础(2)

Spring02 依赖注入DI

Spring容器

由于Spring是用于管理Java Bean对象,也就是Spring中装载很多JavaBean对象,就形象的将Spring称为Java Bean容器,简称 Spring容器。

DI 依赖注入

依赖注入:指将一个计算过程需要用到的资源注入到合适的位置。

依赖:一个计算过程需要的前提条件。

举个例子:

  • 计算圆形面积?PI * r * r  PI是常数,根据计算公式,r是计算园面积的前提条件,可以称为:计算园面积依赖于半径r。

  • 光头强砍树这个事情,需要依赖于“斧子”。

依赖注入:

  • 计算园面积时候,将半径交给公式,就是依赖注入

  • 光头强砍树之前,将斧子交给他,就是依赖注入

Spring Bean 容器提供JavaBean的依赖注入功能,会根据类型或者BeanID将JavaBean注入到合适位置,使程序运行能够得到合适前提依赖对象。

利用@Bean注解进行注入

代码:

  1. 锯子

package cn.yemao.spring02;
import java.io.Serializable;
/** * 斧子类型 */public class Axe implements Serializable { private String name = "开天斧";
@Override public String toString() { return name; }
  1. 工人

package cn.yemao.spring02;
import java.io.Serializable;
public class Worker implements Serializable { private String name = "光头强"; private Axe axe; /** * work:工作 * 这个方法体现了:光头强工作时候依赖于斧子对象! */ public void wrok(){ //字符串连接时候,会自动调用对象的 toString() 然后连接起来 System.out.println(name + "使用" + axe + "砍树"); } public void setAxe(Axe axe) { this.axe = axe; } public Axe getAxe() { return axe; }}
  1. 配置类

package cn.yemao.config;
import cn.tedu.spring02.Axe;import cn.tedu.spring02.Worker;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
@Configurationpublic class Config { @Bean //BeanID = axe public Axe axe(){ return new Axe(); } /** * 利用方法参数注入 axe 对象 * Spring 在运行期间会根据参数的类型自动匹配找到axe对象注入到方法参数 * @param axe2 * @return */ @Bean public Worker worker(Axe a){ Worker worker = new Worker(); worker.setAxe(a); return worker; }}
  1. 测试案例

package cn.yemao;
import cn.tedu.config.Config;import cn.tedu.spring02.Worker;import org.junit.After;import org.junit.Before;import org.junit.Test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestCase { AnnotationConfigApplicationContext ctx; @Before public void init(){ ctx = new AnnotationConfigApplicationContext(Config.class); } @After public void destroy(){ ctx.close(); } @Test public void worker(){ Worker worker = ctx.getBean(Worker.class); //测试结果中出现 开天斧 字样说明注入成功。 worker.wrok(); }}

Spring 依赖注入到匹配规则

  • 首先按照类型自动匹配:

    • 首先根据注入参数的类型(Axe)在Spring容器中寻找类型相同的唯一Bean对象,如果没有找到类型一致的对象,就抛出异常!

    • 如果找到唯一的Axe类型对象,就注入成功。

    • 如果匹配到Axe类型多个对象,就按照BeanID进行匹配

  • 然后按照BeanID进行匹配:

    • 根据变量名和BeanID一致规则进行匹配,如果匹配到唯一的一个Bean对象,就注入成功

    • 否则如果没有匹配到BeanID名称一致的对象就注入失败,抛出异常。

案例,根据名字匹配:

  1. 配置类:

package cn.yemao.config;
import cn.tedu.spring02.Axe;import cn.tedu.spring02.Worker;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
@Configurationpublic class Config { @Bean //BeanID = axe public Axe axe(){ return new Axe(); }
@Bean //BeanID = axe2 public Axe axe2(){ return new Axe(); } /** * 利用方法参数注入 axe 对象 * Spring 在运行期间会根据参数的类型自动匹配找到axe对象注入到方法参数 * @param axe2 * @return */ @Bean public Worker worker(Axe axe2){ Worker worker = new Worker(); worker.setAxe(axe2); return worker; }}
  1. 测试

@Testpublic void worker(){  Worker worker = ctx.getBean(Worker.class);  //测试结果中出现 开天斧 字样说明注入成功。  worker.wrok();}

组件扫描功能也支持自动注入

@Autowired Spring 提供的注解@Resource  Java提供的注解,Spring支持其功能
  • 可以标注在 属性和set方法上,Spring会提供自动注入功能

  • 组件扫描时候自动工作

注入原理:

案例:

  1. 笔类:

package cn.yemao.spring02;
import org.springframework.stereotype.Component;
import java.io.Serializable;
@Componentpublic class Pen implements Serializable { private String name = "万宝龙";
@Override public String toString() { return name; }}
package cn.yemao.spring02;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;
import java.io.Serializable;@Componentpublic class Person implements Serializable { private String name = "小明"; //Spring 会自动从容器中找到pen对象注入到pen变量中 @Autowired private Pen pen;
public void write(){ System.out.println(name+"使用"+pen+"写字"); } public Pen getPen() { return pen; } public void setPen(Pen pen) { this.pen = pen; }}
  1. 配置

@Configuration@ComponentScan("cn.tedu.spring02")public class Config {  //...}
  1. 测试:

@Testpublic void person(){  Person person = ctx.getBean(Person.class);  person.write();}

set方法注入

@Autowired 注解可以标注在属性上,也可以标注在 set方法上,都可以完成属性注入。

@Componentpublic class Person implements Serializable {    private String name = "小明";    //Spring 会自动从容器中找到pen对象注入到pen变量中    //@Autowired //标注在属性上,Spring会注入属性    private Pen pen;    public void write(){        System.out.println(name+"使用"+pen+"写字");    }    public Pen getPen() {        return pen;    }        @Autowired //Spring 会自动调用set方法注入属性    public void setPen(Pen pen) {        System.out.println("调用了setPen()");        this.pen = pen;    }}

构造器注入

@Autowired 注解可以标注在构造器上,完成属性注入。

@Componentpublic class Person implements Serializable {    private String name = "小明";    private Pen pen;    public Person(){}    @Autowried    public Person(Pen pen){        System.out.println("调用Person(pen)");        this.pen = pen;    }    public void write(){        System.out.println(name+"使用"+pen+"写字");    }    public Pen getPen() {        return pen;    }    public void setPen(Pen pen) {        System.out.println("调用了setPen()");        this.pen = pen;    }}

属性注入、set方法注入、构造器注入

  • 3种方式的运算结果一样,基本上可以相互替代

  • 早期 Spring2/Spring3 建议使用 set方法注入

  • Spring4 时代,大多使用 属性 注入,这种方式因为不用写 set方法和构造器方法,使用简洁方便

  • Spring5 时代,推荐使用 构造器注入和set方法注入,不建议使用 属性注入

    • Spring5 中  @Autowried 属性注入时候,会出现不建议使用的提醒!

由于 属性注入代码编写真的太方便了,所以目前仍然广为使用!!!

###@Autowired 和 @Resource 的区别

  • @Autowired 注入时候,先按照参数类型和Bean类型一致的规则进行匹配,如果没有匹配到唯一的Bean对象,在按照属性名和BeanID一致的规则进行匹配。

    • 大致理解:先按照类型匹配,再按照BeanID匹配

  • @Resource 先按照属性名和BeanID一致的规则进行查询,如果找到唯一的一个Bean对象再检查类型,如果类型也一致就注入成功否则抛出异常。如果按照BeanID匹配没有找到唯一的Bean对象,再按照参数类型寻找唯一的对象,找到就注入,找不到就抛出错误

    • 大致理解:先按照BeanID匹配,再按照Bean的类型匹配

  • 如果不严格区别,其最终效果是一样的!

  • @Resource  不能写在构造器上!

###

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
一个简单的例子说明java中spring框架的依赖注入
Spring获取Bean的几种方式
项目中获取Spring的Bean的几种方式
通过实现ApplicationContextAware接口获取bean
Spring学习笔记:第一章 Spring的下载和安装
Spring、Hibernate、Struts1整合的方式
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服