Spring/SpringBoot系列之@Configuration详解【十九】

现在大部分 Spring 项目都采用了基于注解的配置,使用 @Configuration 标记类作为配置类替换 xml 配置文件。一个简单的注解就可以解决很多事情。但是,其实每一个注解背后都有很多值得学习和思考的内容。比如:

  1. @Configuration有什么用?
  2. @Autowired 、 @Inject、@Resource 之间有什么区别?
  3. @Value、@PropertySource 和 @Configuration?
  4. Spring如何处理带@Configuration @Import的类?
  5. @Profile有什么用?
  6. @Configuration 如何嵌套?
  7. Spring如何对Bean进行延迟初始化?
  8. Spring项目怎么进行单元测试?
  9. @Configuration 使用上有哪些约束?

1. @Configuration 基本说明

先看源码:
在这里插入图片描述
在这里插入图片描述
翻译过来大概意思是:表明一个类中声明一个和多个 @Bean 标记的方法,并且这些方法被 Spring 容器管理用于生成 Bean 定义以及在运行时这些 Bean 的服务请求。

如何启动被 @Configuration 标记的类:

源码注释中有这么一段:
在这里插入图片描述
通过注释看到,可以通过使用 AnnotationConfigApplicationContext 来引导启动这个被 @Configuration 注解的类;如果在web项目中,使用 AnnotationContextWebApplicationContext 引导。

下面通过代码进行理解:

  1. 新建一个 MyConfiguration 配置类:
    在这里插入图片描述
    上述 MyConfiguration 加入 @Configuration 注解,表明这是一个配置类。有一个 myBean() 的方法并用 @Bean 进行注释,返回一个 MyBean 的实例,表明这个方法返回的实例需要被 Spring 进行管理。@Bean 如果不指定名称的话,使用方法名作为实例的名称。

  2. 创建 MyBean:
    在这里插入图片描述

  3. 创建测试类:
    在这里插入图片描述
    输出:
    在这里插入图片描述

2. 基于 @ComponentScan 扫描获取 Bean 定义

@Configuration 使用 @Component 进行原注解,因此被@Configuration 注解的类也可以被组件扫描到。另外 @Controller, @Service, @Repository, @Component 四个注解标记的类都能够通过 @ComponentScan 扫描到,其中 @Controller,@Service,@Repository 的注解上都有 @Component,这些注解最大的区别就是使用的场景和语义不一样,这里不进行赘述。

下面通过代码进行理解:

  1. 定义三个类,类上分别用 @Component, @Configuration, @Controller 进行标注:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 在 MyConfiguration上加上 @ComponentScan 注解,扫描上面5个类所在的包:
    在这里插入图片描述
  3. 测试类:
    在这里插入图片描述
    输出:
    在这里插入图片描述

3. @Configuration 和 Environment

@Configuration 通常和 Environment 一起使用,通过使用 @PropertySource,向 Environment 对象提供属性源。

  1. 在 resources 目录下新建 beanName.properties 文件:
    在这里插入图片描述
  2. 新建一个@Configuration配置类,通过 @PropertySource 引入属性文件,同时注入 Environment 对象:
    在这里插入图片描述
  3. 测试:
    在这里插入图片描述
    输出如下:
    在这里插入图片描述

4. @Autowired 、 @Inject、@Resource 的区别

@Inject: 这是 jsr330 的规范,通过 AutowiredAnnotationBeanPostProcessor 类实现的依赖注入。位于 javax.inject 包内,是Java自带的注解。

@Inject
@Named("environment")
Environment env;

注:如果不加 @Named 注解,需要配置与变量名一致即可。

@Autowired: Spring 提供的注解,通过 AutowiredAnnotationBeanPostProcessor 类实现注入。位于org.springframework.beans.factory.annotation 包内。

@Autowired
Environment env;

注:默认是通过 byType 实现注入

@Resource: @Resource 是 jsr250 规范的实现,通过 CommonAnnotationBeanPostProcessor 类实现注入。@Resource 一般会指定一个name属性,如下:

@Resource(name = "environment")
Environment env;

注:默认是通过 byName 实现注入

区别:

@Autowired 和 @Inject 基本是一样的,因为两者都是使用 AutowiredAnnotationBeanPostProcessor 来处理依赖注入。但是@Resource 是个例外,它使用的是 CommonAnnotationBeanPostProcessor 来处理依赖注入。当然,两者都是 BeanPostProcessor。

5. @Value、@PropertySource 和 @Configuration

@Configuration 可以和 @Value 和 @PropertySource 一起使用读取外部配置文件,具体用法如下:

在config 包下新建一个ReadValueFromPropertySource类,代码如下:
在这里插入图片描述

通过 @PropertySource 引入配置文件,使用 @Value 能够获取到属性值。

修改MyBean类,增加一个name属性和一个构造器,再生成其toString() 方法:
在这里插入图片描述
在 SpringConfigurationApplication 中进行测试,如下:
在这里插入图片描述
输出:
在这里插入图片描述

6. @Import 和 @Configuration

详情可以查看这篇文章:Spring/SpringBoot系列之SpringBoot 源码常用注解【九】

7. @Profile

@Profile: 用来实现多环境配置,典型的如数据源。通过激活不同的环境,来进行数据源的切换。

三种激活方式:

  1. 可以通过 ConfigurableEnvironment.setActiveProfiles() 以编程的方式激活;
  2. 可以通过 AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME (spring.profiles.active) 属性设置为 JVM 属性
  3. 通过 @ActiveProfiles 注解在集成测试中以声明方式激活配置文件。

作用域:

  1. 作为类级别的注解,在任意类或者直接与 @Component 进行关联
  2. 作为原注解,可以自定义注解
  3. 作为方法的注解,作用在任何方法

在这里插入图片描述

8. @ImportResource 和 @Configuration

@ImportResource: 这个注解提供了与 @Import 功能相似作用,通常与 @Configuration 一起使用,只不过 ImportResource 是针对 xml 配置文件的,为了兼容旧的传统项目进行改造。下面以一个示例来看一下具体用法:

在config下新建 TestService 类,声明一个构造函数:
在这里插入图片描述
在这里插入图片描述
在 resources 目录下新建 importResources.xml ,为了导入TestService:
在这里插入图片描述
新建一个 ImportResourceWithConfiguration,用于读取配置文件:
在这里插入图片描述
测试:
在这里插入图片描述
输出:
在这里插入图片描述

9. @Configuration 嵌套

@Configuration注解作用在类上,就和普通类一样能够进行相互嵌套,定义内部类。

// 来自JavaDoc
@Configuration
public class AppConfig{

  @Inject
  DataSource dataSource;

  @Bean
  public MyBean myBean(){
    return new MyBean(dataSource);
  }

  @Configuration
  static class DataConfig(){
    @Bean
    DataSource dataSource(){
      return new EmbeddedDatabaseBuilder().build()
    }
  }
}

在上述代码中,只需要在应用程序的上下文中注册 AppConfig 。由于是嵌套的@Configuration 类,DataConfig 将自动注册。当 AppConfig 、DataConfig 之间的关系已经隐含清楚时,这就避免了使用@Import 注解的需要。

10. @Lazy 延迟初始化

@Lazy : 表明一个bean 是否延迟加载,可以作用在方法上,表示这个方法被延迟加载;可以作用在 @Component (或者由@Component 作为原注解) 注释的类上,表明这个类中所有的 bean 都被延迟加载。除了上面两种作用域,@Lazy 还可以作用在 @Autowired 和 @Inject 注释的属性上,在这种情况下,它将为该字段创建一个惰性代理,作为使用 ObjectFactory 或 Provider 的默认方法。

下面来演示一下:

修改 MyConfiguration 类,在该类上添加 @Lazy 注解,新增一个 IfLazyInit() 方法,检验是否被初始化。
在这里插入图片描述
测试类:
在这里插入图片描述
输出你会发现没有关于bean的定义信息:
在这里插入图片描述
但是当吧@Lazy 注释拿掉,你会发现输出了关于bean的初始化信息:
在这里插入图片描述

11. @RunWith 和 @ContextConfiguration

Junit4 测试类,用于注解在类上表示通过 Junit4 进行测试,可以省略编写启动类代码,是 ApplicationContext 等启动类的替换。一般用 @RunWith 和 @Configuration 进行单元测试,这是软件开发过程中非常必要而且具有专业性的一部分:
在这里插入图片描述
在这里插入图片描述

12. @Enable 启动 Spring 内置功能

详情查阅 @EnableAsync,@EnableScheduling,@EnableTransactionManagement,@EnableAspectJAutoProxy,@EnableWebMvc 官方文档

13. @Configuration 使用约束

  1. 必须以类的方式提供(即不是从工厂方法返回的实例)
  2. @Configuration 注解的类必须是非 final 的
  3. 配置类必须是非本地的
  4. 任何嵌套的 @Configuration 都必须是 static 的。
  • 30
    点赞
  • 144
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
@Configuration注解是Spring框架中的一个注解,用于标识一个类是配置类。配置类是用来定义和组织Bean的创建和配置的类。在@Configuration注解的类中,可以使用@Bean注解来定义Bean的创建方法。配置类中的@Bean方法会在容器启动时被调用,并将返回的对象注册为Bean供其他组件使用。 在引用中的示例代码中,@Configuration注解被用于标识MyConfig类为一个配置类,并通过value属性设置了配置类的名称为"lixlConfig"。这样,在其他地方引用该配置类时可以使用这个名称来指定。 在引用中的示例代码中,通过使用Spring Boot的启动器类MainApplication,可以获取到容器中所有Bean的名称。这样可以验证配置类是否被正确加载,并且可以查看配置类的名称是否与预期一致。 在引用中的示例代码中,使用@Configuration注解的MyConfig类的value属性设置为"lixlConfig",并将proxyBeanMethods属性设置为false。该属性用于控制是否开启代理Bean方法的功能。当该属性为true时(默认值),Spring容器会根据@Bean方法的返回类型生成一个代理对象,用于控制方法的调用。当该属性为false时,Spring容器不会生成代理对象。 总结起来,@Configuration注解用于标识一个类是配置类,并通过其value属性设置配置类的名称。配置类中可以使用@Bean注解定义Bean的创建方法。@Configuration注解还可以通过proxyBeanMethods属性控制是否开启代理Bean方法的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [springboot @Configuration注解](https://blog.csdn.net/weixin_38879931/article/details/122899017)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [springboot @Configuration 注解详解](https://blog.csdn.net/nruuu/article/details/126798703)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值