Spring(二):IoC

SpringBoot: 2.1.1

1. IoC简介

IoC容器是Spring的核心,可以说Spring是一种基于IoC容器编程的框架,Spring Boot是基于注解的开发Spring IoC.

IoC是一种通过描述来生成或者获取对象的技术,该技术不是Spring设置也不是Java所独有的.

在Spring中把每一个需要管理的对象称为Spring Bean,而Spring管理这些Bean的容器称之为Spring IoC容器,所有的IoC容器都需要实现接口BeanFactory.它具有两个基本的功能:

  • 通过描述管理Bean,包括发布和获取Bean
  • 通过描述完成Bean之间的依赖关系

2. 装配Bean

2.1 通过扫描装配Bean

使用注解@Component@ComponentScan进行扫描装配,其中@Component表明标明哪个类被扫描进入Spring IoC容器,@ComponentScan标明采用何种策略去扫描装配Bean.

注解@SpringBootApplication注入了@ComponentScan

# 注解@Component表明User类将被IoC容器扫描装配,"user"作为Bean的名称.
@Component("user")  
public class User {
    private Long id;
    private String userName;
    ...
}

# @Cofiguration代表这是一个Java配置文件,Spring的容器会根据它来生成IoC容器去装配Bean
# @ComponentScan默认对AppConfig的当前包及其子包进行扫描去装配Bean 
@Configuration
@ComponentScan
public class AppConfig {
}

@ComponentScan的常用属性:

  • basePackages: 定义扫描的包名
  • basePackageClasses: 定义扫描的类
  • includeFilters: 定义满足过滤器条件的Bean才去扫描
  • excludeFilters: 排除满足过滤器条件的Bean

includeFiltersexcludeFilters都需要通过一个注解@Filter去定义,@Filter有一个type类型,可以定义为注解或者正则式等类型,classes定义注解类,pattern定义正则式类.

例如: 将标注了@Service的类不被IoC容器扫描注入

@ComponentScan(basePackages="com.morven.rest.*", excludeFilters = (@Filter(classes = {Service.class})))
2.2 自定义第三方Bean

如果希望将第三方包的类对象也注入到Spring IoC容器中,使用@Bean注解.

@Configuration
public class AppConfig {
    # 通过@Bean会将该函数返回的对象用名称"dataSource"保存在IoC容器中
    @Bean(name="dataSource")
    public DataSource getDataSource() {
        ...
    }
}

3. 依赖注入(Dependency Injection, DI)

描述的是Bean之间的依赖关系

例如:

public interface Person {
    public void service();
}
public interface Animal {
    public void use();
}
@Component
public class BussinessPerson implements Person {
    @Autowired
    private Anminal animal = null;
    @Override
    public void service() {
        this.animal.use();
    }
}

@Component
public class Dog implements Animal {
    @Override
    public void use() {
        System.out.println("Dog...");
    }
}
3.1 注解@Autowired

使用的最多的注解之一,它注入的机制最基本的一条是根据类型.它既可以标注属性,也可以标注方法.

如果我们再添加一个Animal的实现类Cat

@Component
public class Cat implements Animal {
    @Override
    public void use() {
        System.out.println("Cat...")
    }
}

抛出异常:

expected single matching bean but found 2: cat, dog

修改:

@Autowired
private Animal dog = null;

原因: @Autowired首先根据类型找到对应的Bean,如果对应类型的Bean不是唯一的,那么它会根据其属性名称和Bean的名称进行匹配;如果匹配上就使用该Bean,否则抛出异常.

另外: @Autowired是一个默认必须找到对应Bean的注解,如果不确定其标注属性一定存在并且允许被标注的属性为null,那么可以如下配置:

@Autowired(required = false)
3.2 使用@Primary和@Qualifier消除歧义性

由于接口Animal有两个实现类,因此造成@Autowired装配的歧义性,3.1中给出了一种解决方法,但不是最好的方案;而@Primary和@Qualifier给出了更好的解决方案.

  • @Primary: 是一个修改优先权的注解,通过优先级的变换使得IoC容器知道注入哪个具体的实例来满足依赖注入.如下:

    @Component
    # 优先使用该类进行注入
    @Primary
    public class Cat implements Animal {
        ...
    }
    
  • @Qualifier: 有时候Dog和Cat class都带有@Primary注解,那么@Autowired和@Qualifier组合在一起,通过类型和名称一起找到Bean,以此来消除歧义性.如下:

    @Autowired
    @Qualifier("dog")
    private Anminal animal = null;
    
3.3 带有参数的构造方法类的装配

如果有些类只有带有参数的构造方法,则可以使用如下方法::

@Component
public class BussinessPerson implements Person {
    private Anminal animal = null;
    
    public BussinessPerson(@Autowired @Qualifier("dog") Animal animal) {
        this.animal = animal;
    }
    
    @Override
    public void service() {
        this.animal.use();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值