Spring——DI

一 依赖注入

1.1 什么是依赖注入

1.2 @Bean注入

   spring IOC容器提供了依赖注入功能,可以将一个组件依赖到的对象,在使用之前注入到合适位置

  spring IOC解决依赖注入;在配置类congfig中为Bean组件初始化方法增加参数,spring IOC容器会在初始化时候自动根据类型注入Bean组件对象

案例:

 1.创建Saw

package cn.tedu.demo;

import java.io.Serializable;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
public class Saw implements Serializable {
    private String name="开天斧";

    @Override
    public String toString() {
        return name;
    }
}

 2.创建Worker

package cn.tedu.demo;

import java.io.Serializable;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
public class Worker implements Serializable {
    private String name="光头强";

    public Saw saw;

    public void work(){
        System.out.println(name + "使用" + saw +"砍树");
    }

}

 3.创建配置文件

package cn.tedu.context;

import cn.tedu.demo.Saw;
import cn.tedu.demo.Worker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Configuration
public class Config {
    @Bean
    public Saw saw(){
        return new Saw();
    }

    @Bean
    /**
     * spring会自动根据变量类型匹配Bean组件的类型
     * 如果匹配上,就将Bean组件注入到方法参数中*/
    public Worker worker(Saw s){
        Worker worker = new Worker();
        worker.saw=s;
        return worker;
    }
}

 4.测试案例

package cn.tedu.test;

import cn.tedu.context.Config;
import cn.tedu.demo.Worker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
public class TestCase {

    AnnotationConfigApplicationContext ctx;
    @Before
    public void init(){
        ctx=new AnnotationConfigApplicationContext(Config.class);
    }
    @After
    public void destroy(){
        ctx.close();
    }
    @Test
    public void testWorker(){
        Worker worker = ctx.getBean("worker", Worker.class);
        worker.work();
    }
}

 运行结果:

光头强使用开天斧砍树

   spring IOC组件注入时候组件自动匹配规则:

  1. 首先按照注入参数类型查找相应类型的Bean组件,如果没有直接报错误
  2. 如果在是spring容器中能够匹配上唯一类型的Bean组件,则进行注入成功
  3. 如果按照类型匹配到两个bean组件,则查找组件ID和变量名是否匹配,如果匹配则注入成功
  4. 如果组件类型和组件ID都不能很好匹配则报错

注入失败案例

package cn.tedu.context;

import cn.tedu.demo.Saw;
import cn.tedu.demo.Worker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Configuration
public class Config {
    @Bean
    public Saw saw(){
        return new Saw();
    }
    @Bean
    public Saw saw2(){
        return new Saw();
    }

    @Bean
    /**
     * spring会自动根据变量类型匹配Bean组件的类型
     * 如果匹配上,就将Bean组件注入到方法参数中*/
    public Worker worker(Saw s){
        Worker worker = new Worker();
        worker.saw=s;
        return worker;
    }
}

运行结果:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'worker' defined in cn.tedu.context.Config: Unsatisfied dependency expressed through method 'worker' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cn.tedu.demo.Saw' available: expected single matching bean but found 2: saw,saw2

碰到这种问题,只需要将需要注入的类型名改为@Bean相同的类型名

1.3 @Autowired

  spring提供的组件扫描功能,在扫描时候也可以完成依赖注入,这样可以减少编码提高编程效率

案例

创建电锯类Saw

package cn.tedu.demo;

import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Component
public class Saw implements Serializable {
    private String name="开天斧";

    @Override
    public String toString() {
        return name;
    }
}

创建工人类Worker

package cn.tedu.demo;

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

import java.io.Serializable;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Component
public class Worker implements Serializable {
    private String name="光头强";

    @Autowired
    public Saw saw;

    public void work(){
        System.out.println(name + "使用" + saw +"砍树");
    }

}

创建配置类

package cn.tedu.context;

import cn.tedu.demo.Saw;
import cn.tedu.demo.Worker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Configuration
@ComponentScan(basePackages = "cn.tedu.demo")
public class Config {
    
}

测试案例

package cn.tedu.test;

import cn.tedu.context.Config;
import cn.tedu.demo.Worker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
public class TestCase {

    AnnotationConfigApplicationContext ctx;
    @Before
    public void init(){
        ctx=new AnnotationConfigApplicationContext(Config.class);
    }
    @After
    public void destroy(){
        ctx.close();
    }
    @Test
    public void testWorker(){
        Worker worker = ctx.getBean("worker", Worker.class);
        worker.work();
    }
}

测试结果

光头强使用开天斧砍树

1.4 set方法注入

 测试案例:

 

二 IOC/DI解耦

2.1 利用接口解耦

   利用spring IOC容器提供的DI可以将工具对象注入给工人对象,继而解决之间的依赖关系,并且由于依赖于接口,所以利用spring IOC就可以控制组件的组合关系,实现松耦合

案例:利用spring实现解耦

声明工具接口

package cn.tedu.demo2;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
/**
 * 抽象的工具类型
 * */
public interface Tool {
}

声明工人类

package cn.tedu.demo2;

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

import java.io.Serializable;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Component
public class Worker implements Serializable {
    private String name="光头强";

    @Autowired
    private Tool tool;

    public void work(){
        System.out.println(name + "使用" + tool +"砍树");
    }
}

声明电锯类

package cn.tedu.demo2;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
public class Saw implements Tool{
    private String name="小锯子";

    @Override
    public String toString() {
        return name;
    }
}

声明斧子类

package cn.tedu.demo2;

import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Component
public class Axe implements Serializable,Tool{
    private String name="开天斧";

    @Override
    public String toString() {
        return name;
    }
}

配置类

package cn.tedu.context2;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Configuration
@ComponentScan(basePackages = "cn.tedu.demo2")
public class Config {
}

测试类

package cn.tedu.test;

import cn.tedu.context2.Config;
import cn.tedu.demo2.Worker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
public class TestCase2 {
    AnnotationConfigApplicationContext ctx;

    @Before
    public void init(){
        ctx=new AnnotationConfigApplicationContext(Config.class);
    }
    @After
    public void destroy(){
        ctx.close();
    }
    @Test
    public void testWorker(){
        Worker worker = ctx.getBean("worker", Worker.class);
        worker.work();
    }
}

测试结果

光头强使用开天斧砍树

2.2 @Autowired注入规则

  

 

 案例:将斧子类和电锯类都加上@Component注解

1.在斧子类上设置自定义BeanID

package cn.tedu.demo2;

import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Component("tool")
public class Axe implements Serializable,Tool{
    private String name="开天斧";

    @Override
    public String toString() {
        return name;
    }
}

测试结果:

光头强使用开天斧砍树

2.重构Worker类,设定@Qualifier("saw")

package cn.tedu.demo2;

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

import java.io.Serializable;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Component
public class Worker implements Serializable {
    private String name="光头强";

    @Autowired
    @Qualifier("saw")
    private Tool tool;

    public void work(){
        System.out.println(name + "使用" + tool +"砍树");
    }
}

测试结果:

光头强使用小锯子砍树

2.3 同时使用@Bean @Component

  

1.利用@Bean在配置类Config中声明组件

package cn.tedu.context2;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.util.Date;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Configuration
@ComponentScan(basePackages = "cn.tedu.demo2")
public class Config {
    @Bean
    public Date date(){
        return new Date();
    }
}

 2.利用@Component声明组件,注入Date类型组件

package cn.tedu.demo2;

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

import java.util.Date;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
@Component
public class Employee {
    private String name="傻狍子";

    @Autowired
    private Date date;

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", date=" + date +
                '}';
    }
}

3.测试案例

@Test
    public void testEmployee(){
        Employee employee = ctx.getBean("employee", Employee.class);
        System.out.println(employee);
    }

测试结果:输出当前系统时间,表示Date注入成功

Employee{name='傻狍子', date=Sat Oct 30 21:32:46 CST 2021}

案例:@Component 声明的组件注入到@Bean声明的组件

1.声明Bean类型

package cn.tedu.demo2;

/**
 * @Author Mr WeiLiang
 * @Date 2021/8/5 0005 09:22
 * @Version 1.0
 */
public class Dept {
    private String name="小良哥";
    private Employee manager;

    public void setManager(Employee manager){
        this.manager=manager;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "name='" + name + '\'' +
                ", manager=" + manager +
                '}';
    }
}

2.在配置类Config中利用@Bean声明Bean组件

@Bean
    public Dept dept(Employee employee){
        Dept dept = new Dept();
        dept.setManager(employee);
        return dept;
    }

3.测试案例

@Test
    public void testDept(){
        Dept dept = ctx.getBean("dept", Dept.class);
        System.out.println(dept);
    }

测试结果

ept{name='小良哥', manager=Employee{name='傻狍子', date=Sat Oct 30 21:47:32 CST 2021}}

3 使用Properties文件

3.1 Druld 连接池

案例:

1. 导入连接池

 

2.配置Config.java

 

 测试

测试结果

 

3.2 @PropertlesSource 和 Envlronment

   案例:

 

 

 3.3 @Value

  利用@Value可以读取当前系统环境Environment中的信息,注入到变量中,这个方式更加灵活方便

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值