【深入浅出Spring Boot】1、搞懂Spring Boot下的IoC
参考书籍:《深入浅出Spring Boot 2.x》杨开振文章目录1.IoC2.IoC容器3.Spring Boot创建IoC容器3.1 @SpringBootApplicationSpringApplication.run()4.装配Bean到IoC容器5.依赖注入4.1 @Primary4.2 @Qualifier1.IoCIoC:Inversion of Control控制反转。传统的Jav
参考书籍:《深入浅出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);
}
}
这其中需要注意两点:@SpringBootApplication
和SpringApplication.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()
作用是启动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;
}
更多推荐
所有评论(0)