【深入浅出Spring Boot】1、搞懂Spring Boot下的IoC

参考书籍:《深入浅出Spring Boot 2.x》杨开振

1.IoC

IoC:Inversion of Control控制反转。传统的Java项目是程序员手动用new来实例化对象,而Spring是用IoC容器来管理对象(Spring中把需要管理的对象称为Bean)
控制:即实例化对象的权力
反转:由程序员手动用new关键词实例化变为Spring IoC容器管理实例化对象

看到这里有几个疑问:
1.什么是IoC容器?
2.怎么把Bean装配到IoC容器里?怎么从IoC容器里获取Bean?
3.怎么解决Bean之间的依赖关系?

2.IoC容器

Spring容器是一个管理Bean的容器,在Spring的定义里,所有IoC容器都要实现接口BeanFactory

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

public interface BeanFactory {
	//前缀
    String FACTORY_BEAN_PREFIX = "&";
    
	//多个getBean方法
    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    <T> ObjectProvider<T> getBeanProvider(Class<T> var1);

    <T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
    
	//是否包含Bean
    boolean containsBean(String var1);
	//Bean是否为单例
    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
	//Bean是否为原型
    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
	//是否类型匹配
    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
	//获取Bean的类型
    @Nullable
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;
	//获取Bean的别名
    String[] getAliases(String var1);
}

源码里有多个getBean方法,有按类型获取Bean的,有按名称获取Bean的。

此处解答了如何从IoC容器中获取Bean?getBean方法
后面会讲的@Autowired就是按类型获取Bean

由于BeanFactory功能不够强大,因此在BeanFactory的基础上还设计了一个更高级的接口ApplicationContext。ApplicationContext是BeanFactory的子接口,除此之外,ApplicationContext还提供了集成AOP、管理消息资源、发布事件、在应用层注入上下文等信息

3.Spring Boot创建IoC容器

以下代码是常见的Spring Boot启动类

@SpringBootApplication
public class DemoApplication {
	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

这其中需要注意两点:@SpringBootApplicationSpringApplication.run()

3.1 @SpringBootApplication

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

	//通过类型排除自动装配类
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {};

	//通过名称排除自动装配类
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};
	//定义扫描包
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};
	//定义被扫描的类
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "nameGenerator"
    )
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

我们可以把 @SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。
其中
@Configuration:代表这是一个Java配置类
@ComponentScan:扫描被@Component (@Service、@Controller、@Mapper等)注解的 Bean
@EnableAutoConfiguration:启用 SpringBoot 的自动配置机制

3.2 SpringApplication.run()

参考:SpringBoot启动流程分析(二):SpringApplication的run方法

作用是启动Spring Boot。

所以整个流程是:@SpringBootApplication中含有@Configuration,所以DemoApplication是个Java配置类。

DemoApplication.class作为参数传入SpringApplication.run()中,SpringApplication.run()在启动SpringBoot的过程中会根据配置类DemoApplication来生成IoC容器。(这里优点模糊,因为有些源码我还读不懂)

4.装配Bean到IoC容器

Spring允许我们通过扫描装配Bean到IoC容器中
@Component :标明哪个类被扫描进入IoC容器
@ComponentScan:采用何种策略去扫描装配Bean

因为Spring Boot启动类的@SpringBootApplication已经包含@ComponentScan,所以我们只需要在我们自定义类前加上@Component (@Service、@Controller、@Mapper等),就可以将其交给IoC容器管理。

5.依赖注入

@Autowired会根据属性找到对应的Bean并注入。
用法如:
在这里插入图片描述
但是当我们需要注入的是接口类,且该接口类有多个实现类时,就会产生歧义
在这里插入图片描述

public interface Animal {
    void say();
}
@Component
public class Cat implements Animal{
    @Override
    public void say() {
        System.out.println("喵喵喵");
    }
}
@Component
public class Dog implements Animal{
    @Override
    public void say() {
        System.out.println("汪汪汪");
    }
}

在这里插入图片描述

5.1 @Primary

@Primary告诉IoC容器,当有多个同类型的Bean时,优先使用我注入

@Component
@Primary
public class Cat implements Animal{
    @Override
    public void say() {
        System.out.println("喵喵喵");
    }
}

报错消失

5.2 @Qualifier

@Primary可能修饰多个类,此时就不能单用@Primary来消除歧义,@Qualifier的配置项value需要一个字符串定义,这样Autowired就会通过类型和名称一起找到Bean

@Component
public class TestAnimal {
    @Autowired
    @Qualifier("dog")
    private Animal animal;
}
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值