SpringBoot 01 IOC
Springboot 与 Spring
Spring 是轻量级开发应用框架。它通过 IOC 容器自动管理 java 对象。并且提供 20 多种模块。
Spring 需要开发人员手动配置多种模块,协同作业。Springboot 通过自动配置简化 Spring 框架配置和开发流程。Springboot 的特点是:
- 根据依赖自动配置,减少配置工作量。
- 内嵌 web 服务器。
- 通过 starter 简化依赖管理。
IOC 容器
Spring 容器的目的是自动管理 Java 对象:创建对象,装配对象,使用以及销毁。被容器管理的 java 对象称为 bean。
Spring 自带多种容器,可以分为两类。第一类实现BeanFactory 接口,提供基本依赖注入。第二类实现 ApplicationContext 接口(它是 BeanFactory 的子接口),额外提供属性文本配置,发布应用事件等功能。比如 AnnotationConfigWebApplicationContext 就是 web 服务常用的容器。
bean 的生命周期
普通对象的生命周期由 JVM 管理。bean 的生命周期由 IOC 容器和 JVM 共同管理。bean的生命周期步骤:
- 实例化
- 注入对象的属性,类定义的字段。
- 注入容器的属性。如果 bean 实现 BeanNameAware 接口,则容器将 bean 在容器中的 id 传入 bean。同理,BeanFactoryAware 接口将 BeanFactory 容器实例传入 bean。ApplicationContextAware 接口将 ApplicationContext容器实例传入 bean。
- 如果 bean 实现 BeanPostProcessor 接口,InitializingBean, BeanPostProcessor 接口,容器调用 bean 对应方法。
- 至此,bean 已经可以被使用了,它们被容器注销或者随容器一起注销。
- 注销前,如果 bean 实现 DisposableBean 接口,容器调用 bean 对应方法。
自动装配 bean
Spring 从两个角度实现自动装配:
- componentscan,组件扫描,自动发现上下文创建的 bean。
- autowiring,自动装配,满足 bean 之间的依赖。
@ComponentScan 注解使得 Spring 搜索特定条件下带有 @Component 注解的类。Spring 自动为 @Component 注解的类创建 bean。
执行构造器方法时,@Autowired 注解通知 Spring 传入一个 Card 类型的 bean。
@Component
public class User {private Card card;@Autowiredpublic User(Card card) {this.card = card;}
}// basePackages 定义扫描条件,可以是包名,类名,类型
@ComponentScan{basePackages = {}}
public class UserConfig {
}
@Profile
@Profile 注解允许 Spring 按照 profile 环境参数创建 bean。
根据 spring.profiles.active 属性和 spring.profiles.default 属性指定 profile 参数。
@Configuration
public class Config {@Bean()@Profile("dev")public DataSource sourceDev() {}@Bean()@Profile("prod")public DataSource sourceProd() {}
}
@Conditional
@Conditional 与 @Profile 注解一样作为创建 bean 的条件。但是更加灵活。
@Bean
@Conditional(MyCondition.class)
public User user() {}public class MyCondition implements Condition {// context 是容器上下文,metadata 是 @Conditional 注解的类的所有注解@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 判断条件,返回 true 则创建 user bean,false 则不创建}
}
@Priamry
如果 spring 可以选择多个 bean,@Primary 注解的 bean 比其他 bean 优先级更高。如果 spring 要选择一个实现 Animal 接口的 bean,优先注入 Dog 类型。
@Component
@Primary
public class Dog implements Animal {}@Component
public class Cat implements Animal {}@Component
public class Mouse implements Animal {}
@Qualifier
与 @Priamry 注解一样, @Qualifier 注解可以实现选择 bean。通过限定名称"bark",将 Dog bean 注入 animal。
@Component
@Qualifier("bark")
public class Dog implements Animal {}@Autowired
@Qualifier("bark")
public void setAnimal {Animal animal}
如果不想在一个类上标记多个 @Qualifier 注解,可以自定义注解。@Bark 注解与 @Qualifier(“bark”) 功能相同,更加类型安全。
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Bark {}
用法变成:
@Component
@Bark
public class Dog implements Animal {}@Autowired
@Bark
public void setAnimal {Animal animal}
bean 作用域
Spring 定义的 bean 作用域:
- singleton:单例。容器中只有一个 bean。
- prototype: 原型。每次获取 bean 都会创建一个新的 bean。
- session:会话。web 应用,每个会话一个 bean。
- request:请求。web 应用,每个请求一个 bean。
默认作用域是单例。@Scope 注解定义 bean 的作用域。
动态注入
Environment 接口是 Spring 配置属性存储接口。它的一个实现是 ConfigurableEnvironment 类。PropertySource 代表属性来源,可以是配置文件,可以是系统变量,可以使命令行参数。
Spring 将 demo.properties 属性文件加载到 Environment 中,从中检索属性作为构造器方法参数。
@Configuration
@PropertySource("classpath:/com/example/demo/resource/demo.properties")
public class Config {@AutowiredEnvironment env;@Beanpublic User user() {return new User(env.get("user.name"));}
}
user.name=A
SpEL
Spring Expression Language 可以将值装配到 bean 属性。