IoC 容器、Bean 和常用注解

IoC(Inversion of Control) 也被称为 DI (Dependency Injection)。
对象通过构造参数、工厂参数、set方法等,确定了依赖关系,而 IoC 容器在创建这个对象的时候,将自动为这个对象注入其所需要的依赖。这个过程,就是非常基础的控制反转(IoC)。

beans,就是上面所述由 IoC 容器创建并管理的对象。

IoC 容器

org.springframework.context.ApplicationContxt接口代表了 Spring 的 IoC 容器,并负责实例化、配置、装配各类 beans。这个过程,依赖于配置元数据(configuration metadata),而配置元数据,就是 XML 文件、Java 注解或者 Java 代码。

1
2
3
4
5
6
@SpringBootApplication
public class CustomAutoConfigApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(CustomAutoConfigApplication.class, args);
}
}

Bean 生命周期管理

Bean 的生命周期,大致分为 Bean 定义、Bean初始化、Bean的生存期、Bean的销毁。

Bean 定义

  • Spring 通过在如 scanBasePackages 设置的扫描路径,找到带有 @Component 类。即,进行资源定位。
  • 解析文件,将定义信息保存起来。
  • 将定义信息发布到 IoC 容器中。注意,这里仍然时 Bean 定义,并没有实例化。

初始化

初始话过程如下所示:

图片来源 《深入浅出Spring Boot 2.x》

整个生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Component
public class Apple implements Fruit, BeanNameAware, BeanFactoryAware,
ApplicationContextAware, InitializingBean, DisposableBean ,BeanPostProcessor {

private String TGA = Apple.class.getSimpleName() + " ";

@Override
public String getFruitName() {
return "Apple";
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println(TGA+"set bean factory......");
}

@Override
public void setBeanName(String name) {
System.out.println(TGA+"set bean name:"+ name);
}

@Override
public void destroy() throws Exception {
System.out.println(TGA+"destroy......");
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(TGA+"set Application context...");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println(TGA+"after property set......");
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(TGA+"postProcessAfterInitialization,beanName:"+ beanName);
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(TGA+"postProcessBeforeInitialization, beanName:"+ beanName);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
}

常用注解

注解 @Component

表明这个类将被 Spring IoC容器扫描装配,从而建构出一个 Bean。如下所示,“apple”将作为这个 Bean 的名称。默认情况下,IoC 容器会把类名的第一个字母小写,其它不变,作为 Bean 的名称放入到 IoC 容器中。

1
2
3
@Component("apple")
public class Apple {
}

注解 @ComponentScan

这里加入了 @ComponentScan ,表明它会进行扫描,但是它只会扫描 UserConfig 所在当前包和子包。

1
2
3
4
5
@Configuration
@ComponentScan
public class UserConfig{

}

测试:

1
2
3
4
ApplicationContext context1 = new AnnotationConfigApplicationContext(UserConfig.class) ;
User user = context1.getBean(User.class) ;
user.setName("test");
System.out.println(user.getName());

注解 @Configuration

@Configuration 代表这是一个 Java 配置文件(相当于一个xml配置文件),Spring 容器将会根据它来装配 Bean(xml 中的 )。即,bei’ta被它标记的类中,通常,其返回值通常会被 IoC 容器管理,被标记为 @Bean。

注解 @Bean

表明方法返回的对象将被 IoC 容器管理。

注解 @Autowired

@Autowired 提供这样的规则:首先,它会根据类型找到对应的 Bean,如果对应类型的 Bean 不是唯一的,那么,它会根据期属性名称和 Bean 的名称进行匹配,如果匹配的上,就使用该 Bean,否则,抛出异常(如果 @Autowired 属性 required 为 false,则该值为 null)。

1
2
3
public interface Fruit {
String getFruitName() ;
}
1
2
3
4
5
6
7
@Component
public class Apple implements Fruit{
@Override
public String getFruitName() {
return "Apple";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public class Person {
@Autowired
private Fruit fruit ;

public boolean eatFruit(){
if(fruit != null){
System.out.println("person eat" + fruit.getFruitName());
return true ;
}else
return false ;
}
}

@Autowired 可以除了用在属性上,还可以用于方法上,构造参数中。

1
2
3
4
private Fruit fruit ;
public Person(@Autowired @Qualifier("apple") Fruit fruit){
this.fruit = fruit ;
}

注解 @Primary

注解 @Primary 是一个修改优先注解。根据 @Autowired 的注入规则,我们知道,在进行注入时,容易产生歧义:即,IoC 容器由于找到多个同类型的可注入对象,而不知道要注入哪个。
@Primary 将告诉 IoC 容器,当发现有多个同样类型的 Bean 时,将优先注入使用了 @Primary 注解的 Bean。

1
2
3
4
5
@Component("apple")
@Primary
public class Apple implements Fruit{

}

注解 @Quelifier

对于 @Primary 来说,同样可能会导致歧义,可能有多个同类 Bean 被添加了 @Primary 注解。
在 BeanFactory 中,实际上有一个通过名称和类型找到对象的方法。而使用 @Quelifier 就可以指定 Bean 名称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class Person {
@Autowired
@Qualifier("apple")
private Fruit fruit ;

public boolean eatFruit(){
if(fruit != null){
System.out.println("person eat" + fruit.getFruitName());
return true ;
}else
return false ;
}
}

注解 @Service

@Service 所标记的类,标识该类提供业务功能。本质上,其实就是 @Component:

1
2
3
4
5
6
7
8
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
@AliasFor(annotation = Component.class)
String value() default "";
}

注解 @Controller

@Controller 标明其标注的类是处理器,这里更多的其实是标识意义。通常,它会和 @RequestMapping 注解一起使用。@RequestMapping 负责将网络请求的处理映射到 @Controller 标记的对象中的方法。

1
2
3
4
5
6
7
8
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}

注解 @Repository

@Repository 标记该对象扮演数据仓库的角色,负责数据管理。

1
2
3
4
5
6
7
8
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
@AliasFor(annotation = Component.class)
String value() default "";
}

参考书籍
《深入浅出Spring Boot 2.x》

参考链接
Spring Core Technologies

© 2024 YueGS