SpringBoot(五)之新增注解

简介: 用于 Spring MVC 测试,仅加载 Web 层。

Spring Boot 提供了许多注解来简化开发过程,增强配置能力和提高生产力。以下是一些常用的 Spring Boot 注解及其用途:


核心注解

@EnableAutoConfiguration

@EnableAutoConfiguration 是 Spring Boot 中的一个核心注解,它的主要作用是启用 Spring Boot 的自动配置机制。这个注解告诉 Spring Boot 基于应用程序的类路径设置、其他 bean 和各种属性设置来自动配置 Spring 应用上下文。


详细作用


自动配置 Bean:根据项目依赖的库自动配置相应的 Spring Bean。例如,如果项目依赖中包含 spring-boot-starter-web,@EnableAutoConfiguration 会自动配置 Spring MVC 相关的 bean。

简化配置:通过自动配置,开发者不再需要手动编写大量的配置类,只需要少量的自定义配置即可实现复杂的功能。

条件配置:自动配置是有条件的,依赖于特定的条件注解(如 @ConditionalOnClass、@ConditionalOnMissingBean 等),只有在满足这些条件时才会生效。例如,只有在类路径中存在 DataSource 类时,才会配置数据源相关的 bean。

配置覆盖:开发者可以通过在应用中定义相同类型的 bean 来覆盖自动配置的 bean,从而实现自定义的行为。

使用方法


通常情况下,不需要直接使用 @EnableAutoConfiguration,而是通过 @SpringBootApplication 间接启用。@SpringBootApplication 是一个组合注解,包括 @EnableAutoConfiguration、@ComponentScan 和 @Configuration。


@SpringBootApplication

组合注解,包括 @Configuration、@EnableAutoConfiguration 和 @ComponentScan。

用于标注主配置类,启用自动配置和组件扫描。


@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

@SpringBootApplication标识的类作为SpringApplication.run的参数运行,SpringApplication.run()方法在运行时,会创建Spring容器,这时@SpringBootApplication由于包含@Configuration注解,所以该类作为配置类给Spring,


Spring在创建容器的时候,解析该类上的所有注解,包括


@EnableAutoConfiguration,开启SpringBoot的自动配置功能,自动配置功能用于扫描SpringBoot组件的相关配置的SpringBean,并自动装载这些Bean。


@ComponentScan,用于扫描本身项目中(自己当前写的项目)需要扫描的Bean的包路径,默认为@SpringBootApplication标注的类的当前包以及子包。


在SpringBootConfigApplication同级目录下创建TestApplication


public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestMainConfig.class,args);
    }
}

在config目录下创建TestMainConfig

@SpringBootApplication(scanBasePackages = "cn.axj.springbootstart")
public class TestMainConfig {
}

项目结构如下:




打开TestApplication,并运行main方法,项目正常运行。


                    .__                  __
_____    _______  __|__|____    ____    |__|__ __  ____
\__  \  /  _ \  \/  /  \__  \  /  _ \   |  |  |  \/    \
 / __ \(  <_> >    <|  |/ __ \(  <_> )  |  |  |  /   |  \
(____  /\____/__/\_ \__(____  /\____/\__|  |____/|___|  /
     \/            \/       \/      \______|          \/


    :: spring boot config ::                (2.0)
       spring-boot-config-test

2024-05-17 10:19:28.709  INFO 12896 --- [           main] cn.axj.springbootstart.TestApplication   : Starting TestApplication using Java 1.8.0_261 on DESKTOP-SQBHU59 with PID 12896 (D:\practise\spring-all\spring-boot-config\target\classes started by aoxiaojun in D:\practise\spring-all)
2024-05-17 10:19:28.711  INFO 12896 --- [           main] cn.axj.springbootstart.TestApplication   : No active profile set, falling back to 1 default profile: "default"
.....

此时项目中有两个入口,分别是TestApplication和SpringBootAnnotationApplication


将SpringBootAnnotationApplication中的@SpringBootApplication注解去掉,并执行mvn clean package,会看到如下报错



Unable to find a single main class from the following candidates [cn.axj.springbootstart.SpringBootAnnotationApplication, cn.axj.springbootstart.TestApplication]

这是因为打包过程中,发现有两个入口,不知道选用哪个。


条件注解


Spring原生Conditional注解


Spring中有一个功能,可以根据条件来决定一个类型的Bean是否作为候选组件加入到容器中,所以Spring定义了一个注解**@Conditional**,用来在定义Bean的时候给他上条件,根据条件来判断是否加入到Spring容器中。 @Conditional注解如下



public @interface Conditional {
    Class<? extends Condition>[] value();
}

内部有一个Class属性需要继承自Condition。Condition如下

@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
手写Conditional注解


现在来手写实现一个自己的@MyConditionalOnClass注解功能


  1. 定义@MyConditionalOnClass的条件判断类MyConditionOnClass
public class MyConditionOnClass implements Condition {
    
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(MyConditionalOnClass.class.getName());
        String clazz = (String) annotationAttributes.get("value");
        try {
            //尝试加载该类,如果能正常加载,则条件返回true,不能则返回false
            Class.forName(clazz);
            return true;
        }catch (Exception e){
            return false;
        }
    }
}
  1. 定义@MyConditionalOnClass
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({MyConditionOnClass.class})
public @interface MyConditionalOnClass {
    String value();
}
  1. 测试


  • 创建空Bean类MyBean
public class MyBean {
}
  • 创建空条件类ConditionBean
public class ConditionBean {
}
  • 创建配置类BeanConfiguration,并尝试注入MyBean,加上@MyConditionalOnClass条件注解
@Configuration
public class BeanConfiguration {
    @Bean
    @MyConditionalOnClass(value = "cn.axj.springbootstart.config.ConditionBean")
    public MyBean myBean(){
        //如果该Bean被创建了,则打印该信息
        System.out.println("myBean被创建");
        return new MyBean();
    }
}

启动SpringBootAnnotationApplication项目,观察console控制台,可以看到MyBean被创建



将ConditionBean删除,再次启动SpringBootAnnotationApplication项目,观察console控制台,可以观察MyBean没有被创建,条件注解生效。


@ConditionalOnProperty

根据配置属性的存在或值来条件性地配置 bean。



@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public class MyFeatureConfig {
}
@ConditionalOnMissingBean
  • 当容器中缺少指定类型的 bean 时,才创建当前 bean。
@ConditionalOnMissingBean(MyService.class)
@Bean
public MyService myService() {
    return new MyService();
}

多个同类型的bean,只需要注入一个的时候,可以将所有的Bean都定义并配置,所有的Bean均加上@ConditionOnMissingBean注解,这样Spring容器在加载完成一个这个类型的Bean后,后续的就不会再创建。


@ConditionalOnBean

当容器中存在指定类型的 bean 时,才创建当前 bean。



@ConditionalOnBean(MyService.class)
public class MyBeanConfig {
}
@ConditionalOnMissingClass

这个注解用于基于应用程序启动时类路径中的特定类的缺失来有条件地启用 Spring bean 或配置类。当您希望在某些依赖项不可用时提供替代配置或实现时,它特别有用。

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.stereotype.Component;

@Component
@ConditionalOnMissingClass("com.example.SomeClass")
public class MyComponent {
    // Bean implementation here
}

在这个示例中,只有在类路径中缺少 SomeClass 时,MyComponent 才会被注册为一个 Spring bean。如果 SomeClass 存在,MyComponent 就不会被注册。


配置和属性注解

@ConfigurationProperties

用于将属性文件中的配置映射到 Java 对象。



@ConfigurationProperties(prefix = "test.some")
public class AppProperties {
    private String name;
    private String description;
    // getters and setters
}

测试注解

@SpringBootTest
  • 用于 Spring Boot 应用的集成测试。
@SpringBootTest
public class MyApplicationTests {
    @Test
    public void contextLoads() {
    }
}

@WebMvcTest


  • 用于 Spring MVC 测试,仅加载 Web 层。

目录
相关文章
|
7天前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
24 0
|
1月前
|
Java Spring 容器
如何解决spring EL注解@Value获取值为null的问题
本文探讨了在使用Spring框架时,如何避免`@Value(&quot;${xxx.xxx}&quot;)`注解导致值为null的问题。通过具体示例分析了几种常见错误场景,包括类未交给Spring管理、字段被`static`或`final`修饰以及通过`new`而非依赖注入创建对象等,提出了相应的解决方案,并强调了理解框架原理的重要性。
122 4
|
25天前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
|
14天前
|
XML JSON Java
SpringBoot必须掌握的常用注解!
SpringBoot必须掌握的常用注解!
40 4
SpringBoot必须掌握的常用注解!
|
1月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
66 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
16天前
|
存储 缓存 Java
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
56 2
|
16天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
32 1
|
30天前
|
架构师 Java 开发者
得物面试:Springboot自动装配机制是什么?如何控制一个bean 是否加载,使用什么注解?
在40岁老架构师尼恩的读者交流群中,近期多位读者成功获得了知名互联网企业的面试机会,如得物、阿里、滴滴等。然而,面对“Spring Boot自动装配机制”等核心面试题,部分读者因准备不足而未能顺利通过。为此,尼恩团队将系统化梳理和总结这一主题,帮助大家全面提升技术水平,让面试官“爱到不能自已”。
得物面试:Springboot自动装配机制是什么?如何控制一个bean 是否加载,使用什么注解?
|
10天前
|
存储 安全 Java
springboot当中ConfigurationProperties注解作用跟数据库存入有啥区别
`@ConfigurationProperties`注解和数据库存储配置信息各有优劣,适用于不同的应用场景。`@ConfigurationProperties`提供了类型安全和模块化的配置管理方式,适合静态和简单配置。而数据库存储配置信息提供了动态更新和集中管理的能力,适合需要频繁变化和集中管理的配置需求。在实际项目中,可以根据具体需求选择合适的配置管理方式,或者结合使用这两种方式,实现灵活高效的配置管理。
10 0
|
1月前
|
XML Java 数据库
Spring boot的最全注解
Spring boot的最全注解