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 层。

目录
相关文章
|
16天前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
23 0
|
13天前
|
XML Java 数据格式
Spring的注解
Spring框架注解简化了Java应用开发,通过元数据替代XML配置。`@Component`、`@Controller`、`@Service`、`@Repository`都是组件注解,用于标记不同层的类,如`@Controller`用于控制层,`@Service`业务层,`@Repository`数据访问层。它们均会被组件扫描加入IOC容器,`@Component`是通用形式。通过`@ComponentScan`可以配置扫描规则,包括排除和包含特定类型的组件。`@Autowired`自动装配依赖,`@Value`能从属性文件读取值注入字段。`
|
17天前
|
Java API 数据格式
Spring三兄弟:Spring、Spring Boot、Spring Cloud的100个常用注解大盘点
Spring三兄弟:Spring、Spring Boot、Spring Cloud的100个常用注解大盘点
|
1天前
|
XML Java 关系型数据库
面试一口气说出Spring的声明式事务@Transactional注解的6种失效场景
面试一口气说出Spring的声明式事务@Transactional注解的6种失效场景
|
1天前
|
Java 微服务 Spring
【spring cloud】注解@SpringCloudApplication和@SpringBootApplication的区别
【spring cloud】注解@SpringCloudApplication和@SpringBootApplication的区别
|
9天前
|
Java 测试技术 数据安全/隐私保护
Spring Boot中的自定义注解应用
Spring Boot中的自定义注解应用
|
11天前
|
容器
springboot-自定义注解拦截ip aop和ioc
springboot-自定义注解拦截ip aop和ioc
|
15天前
|
前端开发 Java Spring
蓝易云 - 详解SpringBoot的常用注解
以上就是SpringBoot中常用的一些注解,正确理解和使用这些注解,可以帮助我们更好地使用SpringBoot框架进行开发。
15 0
|
16天前
|
Java Spring 容器
Spring5系列学习文章分享---第六篇(框架新功能系列+整合日志+ @Nullable注解 + JUnit5整合)
Spring5系列学习文章分享---第六篇(框架新功能系列+整合日志+ @Nullable注解 + JUnit5整合)
14 0
|
16天前
|
XML Java 数据库
Spring5系列学习文章分享---第五篇(事务概念+特性+案例+注解声明式事务管理+参数详解 )
Spring5系列学习文章分享---第五篇(事务概念+特性+案例+注解声明式事务管理+参数详解 )
13 0