SpringBoot的容器功能

SpringBoot 的组件添加、原生配置文件引入和配置绑定

一、组件添加

1.1 @Configuration

  • 基本使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Configuration
    public class MyConfig {
    //给容器中添加组件
    @Bean
    public User user(){
    return new User("小明",18);
    }

    @Bean("tomcat")
    public Pet pet(){
    return new Pet("tomcat");
    }
    }
    • @Configuration :告诉SpringBoot这是一个配置类,就是以前的配置文件
    • 方法名:组件的id。如果指定了 @Bean 中的 name 属性,那么 name 属性就是组件的id
    • 返回类型:组件类型
    • 返回值:容器中的实例
  • 配置类里面使用 @Bean 标注在方法上给容器注册的组件,默认都是单例的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @SpringBootApplication
    public class MainApplication {
    public static void main(String[] args) {
    // 1.返回ioc容器
    ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
    // 2.从容器中获取组件
    User user1 = run.getBean("user", User.class);
    User user2 = run.getBean("user", User.class);
    System.out.println("组件是否是单例的:" + (user1 == user2));//true
    }
    }
  • 配置类本身也是组件

    1
    2
    MyConfig myConfig = run.getBean(MyConfig.class);
    System.out.println(myConfig);//com.xzxj.config.MyConfig$$EnhancerBySpringCGLIB$$fdebd3e3@7bc9e6ab
  • Spring 5.2 版本以后,@Configuration 注解多了一个 proxyBeanMethods 属性,默认值为 true

    • 代理 bean 的方法

    • 外部无论对配置类中的注册方法调用多少次,获取的都是之前注册到容器中的单例对象

      1
      2
      3
      User user1 = myConfig.user();
      User user2 = myConfig.user();
      System.out.println(user1 == user2);//true
    • 如果 proxyBeanMethods = true ,就是用代理对象调用方法。

    • 如果 proxyBeanMethods = false ,拿到的就不是代理对象,多次调用得到的组件就不是同一个。

  • Full 模式与 Lite 模式

    • Full 模式: proxyBeanMethods = true ,保证每个 @Bean 方法被调用多少次返回的组件都是单实例的。Spring Boot 总会检查该组件是否在容器中存在,如果有就直接取出;如果没有就创建。保持组件单实例。
    • Lite 模式: proxyBeanMethods = false ,每个 @Bean 方法被调用多少次返回的组件都是新创建的。Spring Boot 不会检查注册组件的方法的组件在容器中是否存在。
  • 组件依赖:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Configuration(proxyBeanMethods = true)
    public class MyConfig {
    @Bean
    public User user(){
    User user = new User();
    user.setName("小明");
    //User组件依赖Pet组件
    user.setPet(pet());
    return user;
    }
    @Bean("tomcat")
    public Pet pet(){
    return new Pet("tomcat");
    }
    }
    • 测试方法:

      1
      2
      3
      User user = run.getBean("user", User.class);
      Pet tomcat = run.getBean("tomcat", Pet.class);
      System.out.println("用户的宠物是否是容器中的:" + (user.getPet() == tomcat));//true
    • 如果 proxyBeanMethods = false 输出结果为 false

  • 总结:

    • 如果在只是在容器中注册组件,该组件不被依赖,一般都把 proxyBeanMethods 设置为 false ,这样 Spring Boot 启动就会快一点,加载也快一点。
    • 如果该组件被依赖,就把 proxyBeanMethods 设置为 true ,保证依赖的组件就是容器中的组件。

1.2 常用注解

  • @Bean :标注实例是一个Spring容器
  • @Component :标注是个容器(一般加入配置)
  • @Controller :在Controller层标注由mvc管理
  • @Service :服务层容器
  • @Repository :持久层容器
  • @Import :快速给容器中导入一个组件

1.3 @Import

  • @Import 可以导入bean或者 @Configuration 修饰的配置类。

  • 如果配置类在标准的 Spring Boot 的包结构下,就是 SpringbootApplication 启动类在包的根目录下,配置类在子包下。就不需要使用 @Import 导入配置类,如果配置类在第三方的jar下,我们想要引入这个配置类,就需要 @Import 对其引入到工程中才能生效。因为这个时候配置类不在 Spring Boot 默认的扫描范围内。

  • 默认组件名字就是全限定类名

    1
    2
    3
    4
    5
    @Import({User.class, ObjectMapper.class})
    @Configuration
    public class MyConfig {

    }

1.4 @Conditional

  • 条件装配:满足Conditional指定的条件,则进行组件注入
  • 在SpringBoot底层中,很多自动注入的原理都是依靠 @ConditionalOnMissingBean 注解,进行是否需要自动装配的原则,在类上或者方法上标注这个注解,决定是否需要需要对此类进行生效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration
@ConditionalOnBean(Pet.class) //当容器中有 Pet类型 的组件时生效
//@ConditionalOnBean(name = "tom") //当容器中有 名字为tom 的组件时生效
public class MyConfig {

@Bean
public User user() {
User user = new User();
user.setName("小明");
user.setAge(18);
user.setPet(pet());
return user;
}

//@Bean("tomcat")
public Pet pet() {
return new Pet("tomcat");
}
}
  • 测试方法
1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
// 返回ioc容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//是否包含组件
boolean tomcat = run.containsBean("tomcat");
System.out.println("容器中是否存在tomcat组件:" + tomcat);//false
boolean user = run.containsBean("user");
System.out.println("容器中是否存在user组件:" + user);//false
}
}

二、原生配置文件引入

@ImportResource

可以用来导入spring配置文件

1
2
3
4
5
@Configuration
@ImportResource("classpath:beans.xml")
public class MyConfig {

}

beans.xml

1
2
3
4
5
6
7
8
9
<bean id="zhangsan"  class="com.hzj.entity.User">
<property name="name" value="zhangsan"/>
<property name="age" value="20"/>
</bean>

<bean id="lucy" class="com.hzj.entity.User">
<property name="name" value="lucy"/>
<property name="age" value="24"/>
</bean>

测试方法

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
boolean zhangsan = run.containsBean("zhangsan");
System.out.println("容器中是否存在zhangsan组件:" + zhangsan);//true
boolean lucy = run.containsBean("lucy");
System.out.println("容器中是否存在lucy组件:" + lucy);//true
}
}

三、配置绑定

3.1@ConfigurationProperties

1
2
3
4
5
6
7
@Data
@Component//只有在容器中的组件,才会拥有SpringBoot提供的强大功能
@ConfigurationProperties("mycar")
public class Car {
private String brand;
private Integer price;
}

application.yml

1
2
3
mycar:
brand: bwm
price: 10000

HelloController.java

1
2
3
4
5
6
7
8
9
10
11
@RestController
public class HelloController {

@Autowired
private Car car;

@RequestMapping("/car")
public Car car(){
return car;
}
}

浏览器访问 http://localhost:8080/car ,结果:

{“brand”:”bwm”,”price”:10000}

3.2 @EnableConfigurationProperties

比如如果第三方的组件,不能使用 @Component 注册到容器中。

可以在配置类上使用 @EnableConfigurationProperties(value={class<?>[]}) 开启相关的配置绑定功能,并且把这个组件注册到容器中。

1
2
3
4
5
@Configuration
@EnableConfigurationProperties(Car.class)
public class MyConfig {

}

  • Copyrights © 2020-2023 夕子学姐
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信