Java EE 中的注解

@Controller

@Controller 是 Spring Framework 中的一个注解,主要用于标记在一个类上,表示该类作为 Spring MVC 中的一个控制器(Controller),负责处理用户的 HTTP 请求并返回响应结果。这个注解属于 Spring Web MVC 模块的一部分,用于实现模型 - 视图 - 控制器(MVC)设计模式。

作用

标识控制器类

标注了 @Controller 的类会被 Spring 容器识别为一个 Bean,并纳入到 Spring MVC 的处理流程中。这意味着,Spring 会创建此类的实例,并将其注入到 IOC 容器中管理。

映射请求

在 @Controller 修饰的类中定义方法,通常会在方法上使用如 @GetMapping@PostMapping@PutMapping@DeleteMapping 等注解来指定 HTTP 请求的方法类型(GET、POST、PUT、DELETE 等)及 URI 路径。当请求匹配到这些注解所指定的规则时,相应的方法将会被调用来处理请求。

返回视图或数据

在处理完请求之后,@Controller 中的方法可以通过返回 ModelAndView 对象、字符串(代表视图名称)、RedirectView 对象,或者直接返回 ResponseEntity、JSON 数据等方式向客户端发送响应。

@RequestMapping

@RequestMapping 是 Spring Framework 中用于处理 HTTP 请求的核心注解之一,它可以应用于类级别或方法级别,用于映射 HTTP 请求到相应的处理逻辑。这个注解同样属于 Spring Web MVC 模块,是实现 MVC 设计模式的重要组成部分。

作用

映射请求路径

在类级别使用 @RequestMapping 可以为整个控制器设置一个基本的请求映射路径,类下的每个方法可以根据需要在其基础上添加更具体的映射规则。在方法级别使用时,它可以精确指定一个或多个 HTTP 请求方法(GET、POST 等)以及请求 URI 路径。

1
2
3
@Controller
@RequestMapping("/users")
public class UserController {  }

请求参数和头信息处理

@RequestMapping 还可以结合 params 和 headers 属性,用于限制请求参数和头信息,只有满足特定条件的请求才会被映射到该方法。

内容协商

通过 consumes 和 produces 属性,可以声明处理方法期望接收的请求内容类型(如 application/json)和返回的内容类型,从而支持内容协商。

重定向和视图解析

处理方法返回的内容可以是一个视图名称(Spring MVC 自动进行视图解析),也可以是一个重定向指令,或者是直接的 HTTP 响应体(如 JSON 数据、XML 数据等)。

1
2
@RequestMapping(value = "/list", method = RequestMethod.GET)
public List<User> listUsers() { ... }

@ResponseBody

@ResponseBody 是 Spring MVC 中的一个注解,主要用于方法级别的处理,指示该方法的返回值不应该被视作一个视图名或模型数据,而是直接作为 HTTP 响应体的内容进行输出。

作用

转换响应内容

当 @ResponseBody 注解应用于一个处理方法时,Spring MVC 会利用 HttpMessageConverter 实现类将方法的返回值转换为适合 HTTP 响应的内容类型(如 JSON、XML 或纯文本等)。默认情况下,Spring 提供了一些内置的 HttpMessageConverter,如 MappingJackson2HttpMessageConverter 用于 JSON 格式的转换。

RESTful API 开发

在构建 RESTful Web 服务时,@ResponseBody 注解非常常见,因为它允许方法直接返回 JSON 或 XML 格式的数据,而不是跳转到一个视图页面。这使得服务接口能够以数据的形式对外提供服务,便于前后端分离的开发模式。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{id}")
    @ResponseBody
    public User getUser(@PathVariable Long id) {
        // 获取用户数据...
        return user;
    }
}

@RequestBody

@RequestBody 是 Spring MVC 中的一个注解,用于处理 HTTP 请求体内容的绑定,将请求体中的数据转换为 Java 对象。

作用

数据绑定

当客户端通过 HTTP 请求(通常是 POST、PUT 或 PATCH 方法)发送 JSON、XML 或自定义格式的数据时,@RequestBody 注解会告诉 Spring MVC 使用 HttpMessageConverter 把请求体的内容转换为指定类型的 Java 对象。例如,如果你的请求体包含一个 JSON 格式的用户信息,你可以将它绑定到一个 User 类型的对象。

自动类型转换

Spring 内置了许多 HttpMessageConverter 实现,如 JSON 转换器(MappingJackson2HttpMessageConverter)可以将请求体中的 JSON 数据转换为 Java 对象,反之亦然。如果请求体内容与 Java 类型不匹配,或者请求体内容无法正确解析,Spring MVC 会抛出异常。

复杂数据结构处理

@RequestBody 不仅可以处理简单的 POJO 对象,还可以处理复杂的数据结构,如嵌套对象、集合和数组等。

1
2
3
4
5
6
@PostMapping("/users")
public ResponseEntity<?> addUser(@RequestBody User user) {
    // 在此处,user 对象已经被自动填充了请求体中的 JSON 数据
    userService.add(user);
    return ResponseEntity.ok().build();
}

@PathVariable

@PathVariable 是 Spring MVC 框架中的一种注解,主要用于处理和提取 URL 路径中的动态部分(也称为模板变量或路径变量)。在构建 RESTful API 或者基于 URL 路径参数的 Web 应用时,该注解显得尤为重要。它允许开发者轻松地将 URL 路径中的动态部分映射到控制器方法的参数中,从而使方法能够根据请求的 URL 动态地处理不同的请求目标。

作用

路径变量绑定

在定义 RESTful 资源的 URL 路径时,常常会有动态的部分,比如 /users/{userId} 中的 {userId}。@PathVariable 注解可以将这种动态部分映射到控制器方法的参数中。

类型转换

Spring MVC 会自动将路径变量转换为指定类型的参数,例如上面示例中的 Long 类型。当然,它也能处理其他基本类型及其包装类、String 类型以及自定义类型(只要这些类型能通过 Spring 的 ConversionService 或 Formatter 进行转换)。

可选参数与默认值

虽然 @PathVariable 默认要求路径变量必须存在于 URL 中,但可以通过在注解中设置 required = false 并提供 defaultValue 来指定可选参数和默认值。

正则表达式约束

尽管 @PathVariable 注解本身不支持直接指定正则表达式进行约束,但在某些版本的 Spring 中,可以通过在 @GetMapping、@PostMapping 等注解的 path 属性中使用正则表达式来限定路径变量的格式。

1
2
3
4
5
@GetMapping("/users/{userId}")
public User getUser(@PathVariable Long userId) {
    // 这里的 userId 参数将被赋值为 URL 中的 {userId} 部分
    return userService.getUserById(userId);
}

@RestController

@RestController 是 Spring MVC 框架中的一个特殊注解,它是 @Controller 和 @ResponseBody 的组合,用于创建 RESTful Web 服务的控制器。

作用

标记控制器类

@RestController 注解用于标记一个类作为 Spring MVC 控制器,这意味着该类中的方法将处理 HTTP 请求并返回响应结果。与普通的 @Controller 相比,@RestController 更专注于返回纯数据,而不是视图或 JSP 页面。

自动添加@ResponseBody

在类级别或方法级别使用 @RestController 注解,相当于为每个处理方法都加上了 @ResponseBody 注解。这意味着类中所有处理方法的返回值都会被自动转换为 HTTP 响应体,而不是视图名或模型数据。这对于构建 RESTful API 服务极为便利,可以方便地返回 JSON、XML 或其他结构化的数据。

简化开发流程

使用 @RestController 可以简化 RESTful API 开发的流程,无需在每个方法上手动添加 @ResponseBody 注解,使得代码更加简洁、易于阅读和维护。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        // 返回 User 对象,Spring MVC 将其自动转换为 JSON 并作为响应体返回
        return userService.getUserById(id);
    }
    @PostMapping
    public ResponseEntity<?> addUser(@RequestBody User user) {
        // 添加用户后返回响应
        userService.addUser(user);
        return ResponseEntity.ok().build();
    }
}

@ControllerAdvice

@ControllerAdvice 是 Spring MVC 中的一个注解,它提供了一种全局处理控制器层中异常和增强处理的功能。这个注解可以让开发者定义一个类,该类中的方法将在所有控制器方法执行前后统一处理一些公共逻辑,如异常处理、统一返回格式化等。

作用

全局异常处理

通过在 @ControllerAdvice 标注的类中定义带有 @ExceptionHandler 注解的方法,可以捕获并处理在整个应用程序中 controllers 出现的特定异常。这种方法可以让你统一处理某一类型的异常,而不是在每个 controller 中单独处理。

统一返回结果处理

可以使用 @ModelAttribute 或 @InitBinder 注解的方法来实现对所有 controller 中请求参数的预处理或后处理,例如数据格式化、验证等。

全局数据绑定

在 @ControllerAdvice 类中,可以定义带有 @ModelAttribute 注解的方法,该方法会在每次 controller 处理请求之前执行,可以用来填充一些公共的 model 对象或属性。

跨控制器方法拦截

@ControllerAdvice 类的方法作用域跨越所有标注了 @Controller 或 @RestController 的类,这意味着你在 @ControllerAdvice 类中定义的逻辑将适用于整个应用中的所有控制器。

1
2
3
4
5
6
7
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = {NullPointerException.class})
    public ResponseEntity<String> handleNullException(NullPointerException ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Null Pointer Exception Occurred");
    }
}

@Service

@Service 是 Spring Framework 中的一个注解,它主要用于标记业务层的服务类。这个注解属于 Spring 的核心容器模块,主要应用于面向服务的设计(Service-Oriented Design)。它的功能作用与 @Component 类似,都是作为组件扫描的一部分,用于标记类作为 Spring 容器中的一个 Bean。是 @Component 的一种细化,具有相同的基础功能,即被 Spring IoC 容器自动扫描、检测和管理。

作用

标识服务类

当一个类被 @Service 注解时,它会被 Spring IOC 容器识别并自动注册为一个 Bean,这样就可以在其他类中通过 @Autowired 注解或 XML 配置来注入和使用这个服务类。

事务管理

在 Spring 框架整合了事务管理(如使用 @Transactional 注解)的情况下,标注了 @Service 的类中的方法可以更方便地进行声明式事务管理。也就是说,如果在这样的服务类的方法上添加 @Transactional 注解,那么这些方法就能够支持数据库事务操作。

解耦和封装业务逻辑

@Service 注解的类通常包含了应用的主要业务逻辑,它可以调用 DAO(Data Access Object)来进行数据库操作,处理业务流程,并对外提供服务接口,从而实现业务逻辑与数据访问逻辑的解耦。

@Repository

@Repository 是 Spring Framework 中的一个注解,主要用于标记持久层的组件,如 DAO(Data Access Object)接口或实现类。它属于 Spring Data 模块的一部分,专门用于简化数据访问层的开发工作。

作用

标识 DAO 组件

当一个类被 @Repository 注解时,Spring IoC 容器会识别并自动将其注册为一个 Bean,这样就可以在其他类中通过 @Autowired 注解或 XML 配置来注入和使用这个 DAO。

异常转换

@Repository 注解的类在遇到特定的持久化异常(如 JDBC 的 SQLException、Hibernate 的 HibernateException 等)时,Spring 会将其转换为 DataAccessException 系列的异常,这些异常是 Spring 统一定义的异常体系,便于全局处理和理解。

事务代理

在使用 Spring AOP 进行声明式事务管理时,被 @Repository 注解的类的方法可以享受到事务管理的功能。当类或方法上有 @Transactional 注解时,Spring 会自动为其创建代理对象,并管理事务边界。

组件扫描

在 Spring 配置中启用组件扫描(如 @ComponentScan 注解或 XML 配置)时,@Repository 注解的类会被自动检测并加入到 Spring 容器中。

@Component

@Component 是 Spring Framework 中的一个注解,它是所有受 Spring 容器管理的组件的基础注解,主要用于标记任何类型的 Spring 管理的组件,包括但不限于那些不属于 @Service、@Repository 和 @Controller 这三个特定角色的类。这个注解同样属于 Spring 的核心容器模块。

作用

标识 Bean

@Component 注解的主要作用是将一个普通的 Java 类标记为 Spring 容器中的 Bean,这样 Spring 就可以在启动时通过类路径扫描自动发现并将其纳入到 IoC 容器中进行实例化、配置和管理。当一个类被 @Component 注解时,Spring 的 ClassPathScanningCandidateComponentProvider 会识别它并将其实例化为 Spring IoC 容器中的一个 Bean,允许应用程序通过依赖注入(DI)的方式使用它。

容器管理

标记了 @Component 的类的实例,可以通过 @Autowired 注解或其他注入方式,在其他需要的地方注入并使用。

自定义 Bean 名称

可以通过 value 属性来指定 Bean 在 Spring 容器中的名称,默认情况下,Bean 的名称将是类名的首字母小写的版本。

类型安全

Spring 通过注解来推断 Bean 的类型,可以在其他地方通过类型安全的方式来引用这个 Bean。

组件扫描

结合 Spring 的组件扫描功能(如使用 @ComponentScan 注解或在 XML 配置中设置 <context:component-scan>),Spring 会自动扫描指定包及其子包下的所有 @Component 注解的类,并将其作为 Bean 注册到 Spring 容器中。

@Autowired

@Autowired 是 Spring Framework 提供的一个注解,主要用于处理 Bean 的依赖注入(Dependency Injection, DI)。这是一个基于 Java 注解的注入机制,允许 Spring 容器在运行时自动为 Bean 的字段、构造器参数、方法参数等提供依赖的对象。

作用

字段注入

当 @Autowired 注解应用于类的字段上时,Spring IoC 容器会尝试自动装配一个与其类型兼容的 Bean 到该字段。如果存在多个同类型的 Bean,若没有明确指定 Bean 的名称,则可能会抛出NoUniqueBeanDefinitionException异常;但如果注解中有设置required属性为false,则不会抛出异常,而是将字段值设为null

1
2
3
4
public class MyClass {
   @Autowired
   private SomeService someService;  // Spring 容器会找到 SomeService 类型的 Bean 并注入
}

构造器注入

也可以将 @Autowired 应用于构造器的参数上,此时 Spring 会按照构造器参数类型寻找并注入相应的 Bean。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class MyClass {
   private final SomeService someService;


   @Autowired
   public MyClass(SomeService someService) {
       this.someService = someService;
   }

}

方法注入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Autowired可以放在setter方法或者任意方法上 Spring 容器初始化 Bean 会调用此方法完成依赖注入
public class MyClass {
   private SomeService someService;


   @Autowired
   public void setSomeService(SomeService someService) {
       this.someService = someService;
   }

}

限定注入

如果希望注入某个特定名称的 Bean,可以在 @Autowired 注解中使用 @Qualifier 注解来指定 Bean 的名称。

1
2
3
4
5
public class MyClass {
   @Autowired
   @Qualifier("specificSomeService") // 指定注入名称为'specificSomeService'的 SomeService Bean
   private SomeService someService;
}

默认行为

@Autowired 注解的默认行为是要求必须成功注入,即 required 属性默认为 true。如果找不到匹配的 Bean,Spring 容器启动时会抛出异常。但是,可以通过设置 required=false 来改变这一行为,使得即使找不到匹配的 Bean 也不会抛出异常。

@Resource

@Resource 是 Java EE 标准注解,它用于标记依赖注入(Dependency Injection, DI),最初由 Java Community Process (JCP) 在 JSR-250 标准中定义,后来也被 Spring 框架支持。尽管 Spring 也提供了自己的 @Autowired 注解,但在某些场景下,开发者可以选择使用 @Resource 来实现依赖注入。

作用

自动装配

@Resource 注解可以放在字段、setter 方法或构造器参数上,指示容器为这些成员变量自动装配相应的 Bean。类似于 Spring 的@Autowired,@Resource 可以帮助容器根据类型或名称来查找并注入依赖。

默认行为

与@Autowired 不同的是,@Resource 默认按照 Bean 的名称进行查找,而非类型。如果未指定 name 属性,它会尝试匹配字段名作为 Bean 的名称。只有当无法通过名称找到匹配的 Bean 时,@Resource 才会按照类型进行查找。

限定注入

通过在@Resource 注解中指定 name 属性,可以明确指出要注入的 Bean 的名称。

在 Spring 中的使用

虽然@Resource 不是 Spring 专有的注解,但 Spring 框架完全支持它,所以开发者可以根据项目的实际情况选择使用@Autowired 还是@Resource。

需要注意的是,在非 Spring 环境下(如 Java EE 应用服务器),@Resource 仍然能够生效,因为它遵循 Java EE 的标准。而在 Spring 环境中,两者都可以用于依赖注入,但其行为细节有所不同,尤其是在无法通过名称找到唯一匹配 Bean 时的处理策略。

@Inject

@Inject 是 Java CDI(Contexts and Dependency Injection for the Java EE Platform)规范的一部分,这个规范旨在增强 Java 平台的依赖注入能力。不过,Spring 框架也支持@Inject 注解以实现依赖注入。

作用

依赖注入

@Inject 注解用于指示容器应该将一个依赖项注入到字段、构造器、方法参数或者静态字段上。它允许容器根据类型或有时根据名称(如果提供了@Named 注解)来查找并注入相应的 Bean。

1
2
3
4
public class MyClass {
   @Inject
   private MyService myService;
}

默认行为

@Inject 的行为与 Java EE 环境中的@Resource 类似,都是默认按名称进行查找。在 Spring 环境下,@Inject 和@Autowired 的行为相似,都可以根据类型进行注入,但要注意,Spring 环境中使用@Inject 时不支持自动按名称查找 Bean,除非结合使用@Named 注解。

Java EE 环境与 Spring 环境的差异

在 Java EE 环境中,@Inject 是由容器(如 Glassfish、WildFly 等应用服务器)提供的 CDI 容器处理的,而在 Spring 环境中,@Inject 注解同样可以实现依赖注入,但其背后的实现原理是基于 Spring 自身的 IoC 容器。

与 JSR 330 的关系

@Inject 是 JSR 330(Dependency Injection for Java)规范的一部分,这个规范定义了一系列注解(包括@Inject)用于标准化 Java 的依赖注入。Spring 框架自 3.0 版本开始支持 JSR 330 标准,所以可以跨框架兼容地使用这些注解。 总之,@Inject 是一个跨框架的依赖注入注解,无论在 Java EE 还是 Spring 环境中,都能帮助开发者实现对象的依赖注入,达到解耦和灵活组装组件的目的。

@Configuration

@Configuration 是 Spring Framework 中的一个注解,主要用于定义一个类作为 Spring IoC 容器中的配置类,相当于传统的 XML 配置文件。它标志着一个类可以包含 @Bean 注解的方法,这些方法会返回被 Spring 管理的 Bean 实例。通过 Java 代码替代 XML 配置文件,使得配置更加直观、灵活且易于管理和测试。同时,它也促进了代码的模块化和组件化设计。

作用

定义配置类

当一个类被标注为@Configuration 时,Spring 容器会把它当作一个“配置源”,类中所有的@Bean 注解的方法都会被调用以生成和初始化对应的 Bean。

组合配置

@Configuration 类之间可以通过@Import 注解互相导入,形成一个配置层次结构,便于组织和复用配置。

条件配置

@Configuration 类中的@Bean 方法还可以结合@Conditional 注解,根据不同的条件决定是否创建对应的 Bean。

组件扫描

带有@Configuration 注解的类也会被 Spring 的组件扫描机制(如@ComponentScan)发现,并作为一个特殊的 Bean 进行处理。

Bean 作用域

在@Bean 方法上可以声明 Bean 的作用域,例如@Scope(“singleton”) 或@Scope(“prototype”),来决定 Bean 实例的生命周期。

自动装配

在@Configuration 类内部,可以自由地使用@Autowired 注解进行依赖注入,因为它们也是 Spring 容器管理的 Bean。

@ComponentScan

@ComponentScan 是 Spring Framework 和 Spring Boot 中的一个核心注解,它主要用于自动扫描和注册具有特定注解的类到 Spring 应用程序上下文中,它简化了 Bean 的配置流程,使得应用架构更加模块化和易于管理。

作用

包扫描

@ComponentScan 注解的主要作用是告诉 Spring 框架从指定的包及其子包中扫描识别出符合某种条件的类,并将它们作为 Bean 注册到 Spring 容器中。这样就免去了手动编写大量的 XML 配置文件来声明 Bean 的过程,降低了耦合度,提高了开发效率。

注解类型过滤

默认情况下,@ComponentScan 会识别@Component、@Service、@Repository、@Controller 以及@Configuration 注解的类。当然,可以通过 includeFilters 属性自定义扫描包含哪些注解类型的类。

排除特定 Bean

@ComponentScan 还提供了 excludeFilters 属性,用于排除特定注解类型或命名规则的 Bean 不被扫描和注册。

扫描范围

basePackages属性是最常用的配置,用来指定要扫描的基本包。另外还有basePackageClasses属性,可以接受一个或多个类,Spring 会根据这些类所在的包来确定扫描范围。

作用范围

@ComponentScan 注解通常会出现在带有@Configuration 注解的类上,这样可以确保扫描的 Bean 与当前配置类一起参与到整个应用的自动装配过程中。

定制扫描策略

除了基本的扫描和过滤功能外,还可以通过扩展 TypeFilter 接口来自定义扫描规则,以满足复杂的扫描需求。

@Bean

@Bean 是 Spring Framework 中用于方法级别的注解,主要用于在 Spring IoC 容器中声明和定义一个新的 Bean 实例。当一个方法被标注为 @Bean 时,Spring 容器会调用这个方法来创建并初始化 Bean 对象,并将其加入到 IoC 容器的管理范围之内。@Bean 注解是 Spring 框架中用来显式地配置和管理 Bean 的重要工具,它使得开发人员能够通过 Java 代码而非 XML 配置文件的方式定义和组织 Bean 的创建逻辑,实现了更加灵活、直观和可维护的依赖注入配置。

作用

定义 Bean

在带有 @Configuration 注解的类中使用 @Bean 注解的方法,表示该方法的返回值将作为一个 Bean 注册到 Spring 容器中。

1
2
3
4
5
6
7
8
9
@Configuration
public class AppConfig {

   @Bean
   public MyService myService() {
       return new MyServiceImpl();
   }

}

在上述代码中,myService() 方法会被 Spring 框架调用一次(默认情况下),并将返回的对象作为一个名为 myService 的 Bean 添加到 Spring 容器中。

生命周期控制

通过在 @Bean 方法内直接操作对象的初始化过程,开发者可以更好地控制 Bean 的生命周期,例如设置属性、执行初始化方法等。

依赖注入

在 @Bean 方法内部,可以直接引用其他已定义的 @Bean 方法,这样 Spring 会自动处理这些依赖关系,完成依赖注入。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Bean
public MyService myService(AnotherDependency anotherDependency) {
   MyServiceImpl service = new MyServiceImpl();
   service.setAnotherDependency(anotherDependency);
   return service;
}

@Bean
public AnotherDependency anotherDependency() {
   return new AnotherDependencyImpl();
}

命名与别名

默认情况下,@Bean 注解的方法名就是生成 Bean 的名称。如果需要指定不同的 Bean 名称,可以通过 name 属性来实现。

作用域

通过 @Scope 注解可以给 @Bean 定义特定的作用域,例如单例(singleton)、原型(prototype)或其他自定义作用域。

@Value

@Value 是 Spring Framework 中的一个注解,用于读取配置属性值并将其注入到字段或方法参数中。它可以读取来自多种来源的属性值,如 properties 文件、yaml 文件、环境变量、命令行参数等。用于从不同来源读取配置属性,并将其注入到 Bean 的字段或方法中,方便开发者在运行时动态地调整和使用配置信息。

作用

字段注入

将属性值注入到类的字段中,字段可以是基本类型、包装类型、字符串或其他对象类型。

1
2
3
4
5
6
7
8
9
@Component
public class MyComponent {

   @Value("${property.name}")
   private String propertyName;

   // ...

}

方法参数注入

将属性值作为方法参数传递。

1
2
3
4
5
6
7
8
@Component
public class MyComponent {

   public void someMethod(@Value("${method.argument}") String argument) {
       // ...
   }

}

SpEL 支持

@Value 注解支持 Spring Expression Language(SpEL),因此可以进行更复杂的数据处理和计算。

1
2
@Value("#{systemProperties['os.name']}")
private String operatingSystem;

默认值

如果尝试解析的属性不存在或为空,可以提供一个默认值。

1
2
@Value("${default.property:default_value}")
private String defaultValue;

@Transactional

@Transactional 是 Spring Framework 提供的一个注解,用于管理事务边界,主要应用于数据访问层和服务层的类或方法上,用于声明该方法或类中的所有方法在一个数据库事务中执行。

作用

开启事务

当方法被调用时,Spring 的事务管理器会根据 @Transactional 注解启动一个新的数据库事务。

事务传播行为

@Transactional 注解允许我们指定事务的传播行为,如 REQUIRED(默认)意味着如果当前存在事务则加入该事务,否则新建一个事务。

回滚规则

当方法抛出未被捕获的 RuntimeException 或 Error 时,默认情况下事务会自动回滚。此外,也可以通过 rollbackFor 或 noRollbackFor 属性来指定具体的异常类型以决定是否回滚事务。

隔离级别

可以通过 isolation 属性来指定事务的隔离级别,例如 READ_COMMITTED、REPEATABLE_READ 等,不同的隔离级别有不同的并发控制效果。

超时设置

通过 timeout 属性可以设置事务等待多久之后才抛出异常,单位通常是秒。

@Aspect

@Aspect 是 Spring AOP(面向切面编程)框架中的一个注解,它用于标记一个类作为切面(Aspect),这类切面类中定义了跨越多个类的关注点,即所谓的横切关注点(Cross-cutting Concerns),如日志记录、权限验证、事务管理等。通过定义切面、切点和通知,可以将系统中分散的横切关注点集中处理,提高代码的重用性和可维护性。同时,这种解耦的方式也有利于保持业务逻辑代码的清晰和简洁。

作用

定义切面

当一个类被标注为 @Aspect 时,表示这个类是一个切面,其中包含了对系统中多个模块的交叉关注点的封装。

1
2
3
4
@Aspect
public class LoggingAspect {
   // 切面中的通知(Advice)方法定义
}

定义切点(Pointcut)

在切面类中,可以定义切点表达式,通过 @Pointcut 注解来指定一组目标方法的集合,这些方法将在特定的连接点(Join Point)处执行切面的通知。

1
2
3
4
@Pointcut("execution(* com.example.service.*.*(..))")
public void loggingMethods() {
   // 切点表达式定义,此处表示匹配 com.example.service 包及其子包下所有方法的执行
}

定义通知(Advice)

在切面中,通过各种类型的通知方法来定义具体的操作,如前置通知(Before Advice)、后置通知(After Advice)、环绕通知(Around Advice)、最终通知(After Returning Advice)和异常通知(After Throwing Advice)等。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Before("loggingMethods()")
public void beforeAdvice(JoinPoint joinPoint) {
   // 前置通知,会在目标方法执行前执行
   System.out.println("Executing method: " + joinPoint.getSignature().getName());
}

@AfterReturning(pointcut = "loggingMethods()", returning = "result")
public void afterReturningAdvice(Object result) {
   // 后置通知(返回通知),在目标方法正常返回后执行
   System.out.println("Method executed with result: " + result);
}

织入(Weaving)

Spring AOP 框架会在运行时动态地将切面所定义的通知织入到相应的目标方法执行路径上,从而实现对目标方法的增强或拦截。

@After (后置通知)

作用

@After 注解是一种后置通知(After Advice),它标记的方法会在目标方法(或目标方法链)正常执行完毕后执行,无论目标方法是否抛出了异常。这意味着,只要目标方法开始执行,无论结果如何,后置通知总会被执行。

@Before (前置通知)

作用

@Before 注解是一种前置通知(Before Advice),它标记的方法会在目标方法执行前先被执行。前置通知常常用于在实际执行业务方法前做一些预处理工作,比如权限检查、参数校验等。

@Around (环绕通知)

作用

@Around 注解是一种环绕通知(Around Advice),它是最强大的通知类型。环绕通知能够控制目标方法的完整执行流程,即在目标方法执行前后均可以添加额外的操作,并能决定是否继续执行目标方法以及何时执行目标方法。

@Pointcut

@Pointcut 注解用于定义一个切点表达式,并给它一个标识名称。这个标识名称可以在其他的 AOP 通知注解(如@Before、@After、@Around)中引用,以便让那些通知方法在符合切点表达式的切入点上执行。

作用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Pointcut("execution(* com.example.service..*(..))")
  public void anyMethodInServicePackage() {
   // 这里不需要有实际方法体,只是一个切点表达式的定义
  }

// 引用定义好的切点
@Before("anyMethodInServicePackage()")
public void beforeServiceMethod() {
    // ...
}

在上述代码中,@Pointcut(“execution(* com.example.service..*(..))”) 定义了一个切点表达式,它匹配 com.example.service 包及其子包下的所有方法。然后在 @Before 注解中通过引用切点名称 “anyMethodInServicePackage()” 来指定通知方法应在哪些方法执行前触发。

@PropertySource

@PropertySource 是一个 Spring 框架中的注解,用于指定一组或多个外部属性文件的路径,以便将这些文件中的配置属性导入到 Spring 容器中。通过该注解,我们可以将应用的配置信息从 Java 配置类或者 XML 配置文件中分离出来,以更灵活的方式管理应用程序的配置参数。

作用

@PropertySource 主要用于向 Spring 环境中添加额外的属性源。这些属性可以在后续的 Bean 初始化过程中作为占位符(${...})被解析,也可以直接通过 Environment 对象访问。

使用位置

通常在 Spring 的配置类(使用 @Configuration 注解的类)上声明 @PropertySource。如果需要为 XML 配置文件引入外部属性源,可以使用 <context:property-placeholder><context:property-source> 标签。

基本语法

1
@PropertySource(value = {"file:path/to/file.properties", "classpath:another-file.properties"})

value 属性是一个字符串数组,表示待加载的属性文件路径。每个路径可以是绝对路径(对于文件系统资源)或相对于类路径的路径(对于类路径资源)。 前缀 file: 表示从文件系统加载属性文件,而前缀 classpath: 表示从类路径加载属性文件。如果不指定前缀,默认会尝试从类路径加载。

特性与选项

编码:默认情况下,Spring 使用 JVM 的默认字符集来读取属性文件。如果需要指定特定的字符集,可以使用 encoding 属性,如 @PropertySource(value = "file:config.properties", encoding = "UTF-8")。 失败策略:当指定的属性文件不存在或无法读取时,Spring 默认抛出异常。若希望忽略错误并继续初始化过程,可以设置 ignoreResourceNotFound 属性为 true,如 @PropertySource(value = "file:optional-config.properties", ignoreResourceNotFound = true)

优先级与合并

  • 多个 @PropertySource 注解可以应用于同一个配置类,它们按照定义顺序依次加载,后定义的属性值会覆盖之前定义的同名属性。
  • 如果同时存在 XML 中定义的 context:property-placeholder 和 @PropertySource,两者提供的属性都会被合并到环境变量中。在冲突的情况下,@PropertySource 中的属性具有更高的优先级。

访问属性

在配置类中注入 Environment 对象,然后通过其 getProperty(String key) 方法获取属性值。 在其他 Bean 中,可以通过 @Value("${property.key}") 注解直接注入属性值。 在 SpEL 表达式中,可以使用 ${property.key} 引用属性值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {
   @Autowired
   private Environment env;
   @Bean
   public MyService myService() {
        String someProperty = env.getProperty("my.service.some.property");
        return new MyService(someProperty);
   }
}

@PostConstruct

@PostConstruct 是一个标准的 Java EE 注解,广泛应用于 Spring 框架及其他基于 Java 的依赖注入(DI)和面向切面编程(AOP)框架中。它用于标记在一个 Bean 初始化完成后的回调方法,即当所有必需的依赖注入完成后,容器调用此方法进行进一步的初始化操作。以下是 @PostConstruct 注解的详细解释:

作用

@PostConstruct 注解用于标记在一个 Bean 中需要在构造函数及依赖注入完成后立即执行的方法。这个方法通常用于执行一些必要的初始化逻辑,如数据预加载、连接池初始化、缓存填充等。

使用位置

@PostConstruct 注解应放在无参或仅接受 javax.inject.Inject 注解参数的非静态方法上。该方法通常定义在 Spring Bean 类(即被 @Component, @Service, @Repository, @Controller 等注解标记的类)内部。

执行时机

当 Spring 容器创建并完成对 Bean 的依赖注入后,但在 Bean 被任何其他对象引用之前,会调用标注了 @PostConstruct 的方法。这意味着在此方法内,所有的依赖属性都已经设置完毕,可以安全地访问和操作。

特点

  • 唯一性:一个 Bean 中可以有多个方法使用 @PostConstruct 注解,但它们的执行顺序没有明确保证,除非显式使用 Ordered 接口或 @Order 注解来指定顺序。
  • 异常处理:如果 @PostConstruct 方法抛出异常,Spring 容器会视为 Bean 初始化失败,通常会导致容器启动失败或该 Bean 无法正常使用。

与构造函数的区别

构造函数主要负责对象的实例化,一般用于设置不可变状态或依赖于构造时注入的参数。而 @PostConstruct 方法则是在对象已经完全构造并注入依赖之后执行,用于执行更为复杂的初始化逻辑,可能涉及与其他 Bean 的交互或外部资源的访问。

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Service
public class UserService {

    private final UserRepository userRepository;
    private Map<String, User> cachedUsers; // 假设有一个用户缓存
    
    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    @PostConstruct
    public void initializeCache() {
        cachedUsers = new HashMap<>();
        List<User> allUsers = userRepository.findAll();
        for (User user : allUsers) {
            cachedUsers.put(user.getId(), user);
        }
        log.info("User cache initialized with {} users.", cachedUsers.size());
    }
    
    // 其他业务方法...

}

@PreDestroy

@PreDestroy 是一个标准的 Java EE 注解,同样广泛应用于 Spring 框架及其他基于 Java 的依赖注入(DI)和面向切面编程(AOP)框架中。它用于标记在一个 Bean 销毁前需要执行的清理或资源释放方法。它和@PostConstruct 可以视为一组。

作用

@PreDestroy 注解用于标记在一个 Bean 中需要在销毁前执行的方法。这个方法通常用于执行一些必要的清理工作,如关闭数据库连接、释放系统资源、注销监听器等,确保 Bean 在生命周期结束时能够正确释放其所占用的资源,避免内存泄漏或其他资源未被正确关闭的问题。

使用位置

@PreDestroy 注解应放在无参或仅接受 javax.inject.Inject 注解参数的非静态方法上。该方法通常定义在 Spring Bean 类(即被 @Component, @Service, @Repository, @Controller 等注解标记的类)内部。

执行时机

当 Spring 容器决定要销毁一个 Bean(例如,在容器关闭时,或者由于 Bean 的作用域变化不再需要该 Bean 时),会在 Bean 实例被真正销毁之前调用标注了 @PreDestroy 的方法。这意味着在此方法内,Bean 仍然可以访问其依赖关系和持有的资源。

特点

  • 唯一性:一个 Bean 中可以有多个方法使用 @PreDestroy 注解,但它们的执行顺序没有明确保证,除非显式使用 Ordered 接口或 @Order 注解来指定顺序。
  • 异常处理:尽管 @PreDestroy 方法抛出的异常通常不会阻止 Bean 的销毁,但建议在实现此类方法时妥善处理异常,确保资源得到正确释放。

与 finalize() 方法的区别

finalize() 方法是 Java 中的一个特殊方法,用于在对象被垃圾回收器回收前进行最后一次清理。然而,其执行并不受控且不能保证一定会被执行,因此不适合用于资源管理。相比之下,@PreDestroy 方法的调用由 Spring 容器精确控制,提供了更加可靠的资源释放机制。

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@Service
public class DatabaseConnectionService {

    private Connection connection;
    
    public void establishConnection() throws SQLException {
        connection = DriverManager.getConnection(DB_URL, USER, PASS);
    }
    
    @PreDestroy
    public void closeConnection() throws SQLException {
        if (connection != null && !connection.isClosed()) {
            connection.close();
            log.info("Database connection closed.");
        }
    }
    
    // 其他业务方法...

}

@Profile

@Profile 是 Spring 框架提供的一个条件注解,用于根据激活的 Spring 配置 Profile 来控制 Bean 的创建和注册。通过使用 @Profile,开发者可以实现应用的不同环境(如开发、测试、生产)下的差异化配置和组件启用。

作用

@Profile 注解用于标记某个 Bean、配置类、方法或 @ConfigurationProperties 类,使其仅在特定的 Profile 被激活时生效。这样可以根据运行环境选择性地加载或排除部分 Bean 或配置,实现灵活的环境切换和配置管理。

使用位置

可以将 @Profile 注解应用于以下位置:

  • Bean 类(如服务类、控制器类、组件类等)
  • 配置类(使用 @Configuration 注解的类)
  • 方法(通常是配置类中的 @Bean 方法)
  • @ConfigurationProperties 类

基本语法

1
@Profile({"dev", "test"})

value 属性是一个字符串数组,表示该 Bean 或配置只应在哪些 Profile 被激活时生效。当当前活动的 Profile 与列表中的任何一个相匹配时,该 Bean 或配置就会被创建和注册到 Spring 容器中。

激活 Profile

有多种方式可以激活 Profile:

  • 在应用启动时通过命令行参数指定:--spring.profiles.active=dev,test
  • application.propertiesapplication.yml 文件中设置:spring.profiles.active=dev,test
  • 在 Web 应用上下文中通过请求参数指定:http://localhost:8080/context-path?spring.profiles.active=dev,test
  • 在代码中通过 SpringApplication.setAdditionalProfiles(...)SpringApplicationBuilder.profiles(...) 方法设置

组合与排除

可以使用包含逗号的字符串(如 dev,!production)来表达复杂的需求,其中 ! 表示排除某个 Profile。例如,@Profile("dev,!production") 表示在 dev Profile 激活且 production Profile 未激活时生效。 对于方法级别的 @Profile,可以结合使用 @Conditional 注解及其派生注解(如 @ConditionalOnProperty、@ConditionalOnClass 等)实现更复杂的条件判断。 示例:

 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
// 仅在 'dev' 或 'test' Profile 下创建此 Bean
@Service
@Profile({"dev", "test"})
public class DevOrTestUserService implements UserService {
    // ...
}

// 仅在 'prod' Profile 下创建此 Bean
@Service
@Profile("prod")
public class ProductionUserService implements UserService {
    // ...
}

@Configuration
public class MyConfig {

    // 仅在 'dev' 或 'test' Profile 下创建此 Bean
    @Bean
    @Profile({"dev", "test"})
    public DataSource devOrTestDataSource() {
        // 返回适用于开发或测试环境的数据源配置
    }
    
    // 仅在 'prod' Profile 下创建此 Bean
    @Bean
    @Profile("prod")
    public DataSource productionDataSource() {
        // 返回适用于生产环境的数据源配置
    }

}

@EnableAsync

@EnableAsync 是 Spring Framework 中的一个注解,主要用于启用异步方法调用的支持。在 Spring 中,通过使用该注解,可以将普通方法标记为异步方法,使其在调用时不阻塞当前线程,而是通过异步任务执行器(如线程池)执行,从而提高系统的并发能力和响应速度。

作用

激活异步处理

当 @EnableAsync 注解被应用到一个配置类上时,Spring 会自动注册一个 AsyncConfigurer 的实现,该实现配置了默认的任务执行器(TaskExecutor),用于处理被 @Async 注解标记的方法。

异步方法定义

使用 @Async 注解标记在 service 类或 repository 类中的方法,意味着当该方法被调用时,不会立即等待方法执行完毕,而是交由异步任务执行器调度执行。

线程池配置

开发者可以通过实现 AsyncConfigurer 接口或在配置类中定义 @Bean 注解的方法来自定义异步任务执行器,比如设置线程池大小、队列容量等参数,以适应不同的异步处理需求。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5); // 设置核心线程数
        executor.setMaxPoolSize(10); // 设置最大线程数
        executor.setQueueCapacity(20); // 设置队列容量
        executor.initialize();
        return executor;
    }
}

@Service
public class SomeService {
    @Async
    public Future<String> asyncMethod(String arg) {
        // 异步处理逻辑
        return new AsyncResult<>("Processed asynchronously with argument: " + arg);
    }
}

AsyncConfig 类启用了异步处理,并配置了一个自定义的线程池。SomeService 类中的 asyncMethod 方法被标记为异步方法,当该方法被调用时,其执行过程将由配置好的线程池管理,不再阻塞主线程。

@Async

@Async 是 Spring Framework 提供的一个注解,用于实现异步方法调用。当此注解应用于一个方法时,表明该方法将被异步执行,即在调用该方法时不会立即等待方法执行完成,而是由 Spring 的 TaskExecutor(任务执行器)在后台线程中执行,主线程可以继续执行其他任务。

作用

异步执行

标注了 @Async 的方法会在调用时切换到另一个线程(通常是由 Spring 的 TaskExecutor 提供的线程池中的线程)上执行,使得方法的执行不会阻塞调用者的线程,从而提升系统性能和响应速度。

配置

要在应用中使用 @Async,你需要首先在某个配置类上启用异步支持,即使用 @EnableAsync 注解。此外,还需要配置一个 TaskExecutor,Spring 会使用它来执行异步任务。如果不显式配置,Spring 会使用一个默认的 SimpleAsyncTaskExecutor。

返回类

异步方法通常返回 java.util.concurrent.Future 或 java.util.concurrent.CompletableFuture,以便调用方在将来某个时间点检查异步方法的执行结果或状态。

注意事项

  • @Async 注解的方法不能是同步的,也不能是静态的。

  • 异步方法通常在 Spring Bean 中使用,因为异步调用的上下文是代理对象,而非原始对象。

  • 不能在同一个类中直接调用一个异步方法,因为 Spring AOP 代理默认不会拦截内部方法调用,可以通过在其他 Bean 中间接调用或者通过 AspectJ 方式解决这个问题。

@EnableScheduling

@EnableScheduling 是 Spring Framework 中提供的一个注解,用于启用定时任务调度功能。当我们在 Spring 应用程序的某个配置类上添加这个注解时,Spring 会自动扫描和注册所有带有 @Scheduled 注解的方法,并通过一个后台调度器(默认是基于 ThreadPoolTaskScheduler)按照预定的规则周期性执行这些方法。

作用

启动定时任务

启用 @EnableScheduling 后,Spring 容器会识别并初始化一个调度器,然后根据配置定期执行带有 @Scheduled 注解的 bean 中的方法。

配合 @Scheduled 使用

@Scheduled 注解用于标记需要定时执行的方法,可以配置 cron 表达式或者固定间隔时间,以便按照指定的调度策略执行任务。

异步执行

默认情况下,被 @Scheduled 注解的方法会在一个后台线程中异步执行,不会阻塞主线程。

配置

除了使用默认的调度器配置,还可以通过自定义 TaskScheduler 或 ScheduledExecutorService 并暴露为 Spring Bean 来覆盖默认的调度器实现。

1
2
3
4
5
6
7
8
9
@Configuration
@EnableScheduling
public class SchedulingConfig {
    @Scheduled(cron = "0 0/5 * * * ?") // 每 5 分钟执行一次
    public void executePeriodicTask() {
        System.out.println("Executing periodic task at " + LocalDateTime.now());
        // 定时任务的具体逻辑
    }
}

@Scheduled

@Scheduled 是 Spring Framework 中提供的一个注解,用于定义和执行定时任务。当你在某个类的方法上使用 @Scheduled 注解时,Spring 会根据注解中配置的时间表达式或间隔时间定期执行该方法。

作用

定时任务

@Scheduled 注解可以用于任何 Spring Bean 中的非静态方法上,标示该方法是一个定时任务,Spring 容器会依据注解中的调度策略自动执行该方法。

调度策略

@Scheduled 支持两种类型的调度策略:

cron 表达式

通过 cron 属性指定一个 cron 表达式,如 0 0/5 * * * ? 表示每 5 分钟执行一次。

fixedDelay/fixedRate

通过 fixedDelay()fixedRate() 指定一个固定时间间隔,单位是毫秒,fixedDelay() 表示两次执行之间的间隔从上次方法执行结束算起,fixedRate() 表示两次执行之间的时间间隔是固定的,不受方法执行耗时影响。

依赖 @EnableScheduling

要使 @Scheduled 注解生效,需要在配置类上开启定时任务支持,即使用 @EnableScheduling 注解。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Configuration
@EnableScheduling
public class ScheduledTasksConfig {
    @Scheduled(cron = "0 0/5 * * * ?")
    public void executeEveryFiveMinutes() {
        System.out.println("Executing scheduled task at " + LocalDateTime.now());
        // 执行定时任务的具体逻辑
    }
    @Scheduled(fixedRate = 10000) // 每 10 秒执行一次
    public void executeWithFixedRate() {
        System.out.println("Executing scheduled task with fixed rate at " + LocalDateTime.now());
        // 执行定时任务的具体逻辑
    }
}

@Conditional

@Conditional 是 Spring Framework 中的一个条件注解,它允许基于特定的条件来决定是否包含或激活某个 Bean 的定义。当条件满足时,Spring 容器才会实例化和注册被注解的 Bean,否则该 Bean 将不会成为应用程序上下文中的一部分。

作用

细粒度控制

通过 @Conditional 注解,开发者可以对 Bean 的创建进行细粒度的控制,根据不同的环境、配置或者其他自定义条件决定是否应该创建和初始化这个 Bean。

自定义条件

@Conditional 注解需要与实现 org.springframework.context.annotation.Condition 接口的类一起使用。这个接口有两个方法 matchesgetMatchOutcome,Spring 会在启动时调用这些方法来评估条件是否满足。

内置条件注解

Spring 提供了一系列预定义的条件注解,如 @ConditionalOnBean@ConditionalOnClass@ConditionalOnExpression@ConditionalOnMissingBean@ConditionalOnMissingClass 等,这些注解可以帮助开发者快速根据类的存在与否、Bean 的存在与否、SpEL 表达式的结果来决定 Bean 是否被加载。

1
2
3
4
5
6
7
8
9
@Configuration
@ConditionalOnClass(MyService.class) // 如果 MyService 类存在,则加载此配置类
public class MyConfiguration {
    @Bean
    @ConditionalOnMissingBean(MyService.class) // 如果没有定义 MyService Bean,则创建此 Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

在这个示例中,MyConfiguration 类仅在 MyService 类存在的时候才会被加载到 Spring 容器中。同时,myService 方法定义的 Bean 只有在 Spring 容器中还没有其他同类型的 Bean(即 MyService 类型的 Bean)时才会被实例化并加入到容器中。 通过 @Conditional 注解及其扩展,Spring 提供了一种灵活的方式来根据运行时环境定制 Bean 的创建逻辑,有利于实现组件的按需加载和动态配置。

@ContextConfiguration

@ContextConfiguration 是 Spring Test 框架中的一个注解,用于指定测试类在运行时所需的 Spring 应用上下文配置信息。这个注解主要在集成测试中使用,它允许开发者明确指出应该使用哪些 XML 配置文件、Java 配置类或基于注解的配置来初始化 Spring 容器。

作用

加载配置

通过 locations 属性指定 Spring 配置文件的位置,可以是 XML 文件路径(如 classpath:/spring/app-context.xml ),也可以是 Groovy 脚本路径。

引用配置类

通过 classes 属性指定 Spring Java 配置类的 Class 对象,Spring 会基于这些类来创建和初始化应用上下文。

激活 Profiles

通过 profiles 属性可以指定 Spring 配置文件中的 Profile,以便在测试环境中激活特定的配置。

初始化参数

还可以通过 inheritInitializersinitializers 等属性来控制上下文初始化器的行为。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = {"classpath:/spring/test-config.xml"}, classes = TestConfig.class)
public class MyServiceTest {

    @Autowired
    private MyService myService;
    
    @Test
    public void testMyService() {
        // 测试代码...
    }

}

// TestConfig.java
@Configuration
public class TestConfig {
    // Spring Java 配置代码...
}

@ExceptionHandler

@ExceptionHandler 是 Spring MVC 框架中用于处理控制器方法抛出的异常的注解。在 Spring Web 应用程序中,当控制器方法在执行过程中抛出异常时,Spring 会尝试找到具有相应 @ExceptionHandler 注解的方法来处理这个异常。

作用

异常处理

标注了 @ExceptionHandler 的方法会在遇到与该方法所处理异常类型相匹配的异常时被调用,从而实现对异常的捕获和自定义处理逻辑。

异常映射

可以将该注解放在控制器类上,为整个类定义通用的异常处理逻辑,也可以放在单个方法上,为特定方法定义个性化的异常处理逻辑。

返回响应

处理异常的方法通常会返回一个 ModelAndView 对象、ResponseEntity 对象、视图名称(字符串形式)或直接返回数据,这样 Spring MVC 就可以根据返回值构造并发送一个包含错误信息的 HTTP 响应给客户端。

支持多种异常类型

一个 @ExceptionHandler 方法可以处理一种或多种异常类型,只需要在注解中列出这些异常类型即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Controller
public class MyController {
    @GetMapping("/users/{id}")
    public String getUserInfo(@PathVariable Long id, Model model) {
        // 假设此处抛出一个 IllegalArgumentException
        throw new IllegalArgumentException("Invalid user ID");
    }
    @ExceptionHandler({IllegalArgumentException.class})
    public String handleIllegalArgument(IllegalArgumentException e, RedirectAttributes redirectAttrs) {
        redirectAttrs.addFlashAttribute("errorMessage", e.getMessage());
        return "redirect:/error";
    }
}

@EnableAutoConfiguration

@EnableAutoConfiguration 是 Spring Boot 中的一个核心注解,它开启了 Spring Boot 的自动配置功能。这个注解背后的思想是尽可能减少开发人员在搭建新项目时所需的配置工作,通过自动配置来识别应用上下文中已经存在的组件,从而自动配置 Spring 容器中可能需要的 Bean。

作用

自动装配

当 Spring Boot 应用启动时,如果发现类路径中有特定的类或 jar 包,Spring Boot 将自动配置相应的 Bean,例如,如果类路径下存在 HSQLDB 的 jar,Spring Boot 会自动配置一个内存数据库。

条件配置

自动配置基于条件注解(如 @ConditionalOnClass@ConditionalOnBean 等),这些条件注解确保只有在满足特定条件(如类路径中存在的类或已经存在的 Bean)时,才进行自动配置。

可定制化

虽然 @EnableAutoConfiguration 提供了大量的自动配置,但开发人员可以根据需要禁用某些自动配置,或者提供自定义的配置覆盖自动配置的默认行为,这通常通过创建一个 @Configuration 类并在其中定义 Bean 或使用 @EnableAutoConfiguration(exclude={...}) 注解来排除不需要的自动配置类实现。

@SpringBootApplication

@SpringBootApplication 是 Spring Boot 中的一个复合注解,它整合了 @SpringBootConfiguration@EnableAutoConfiguration 、@ComponentScan 的功能,是创建 Spring Boot 应用程序的主要入口点。

用它标记的主类,Spring Boot 会自动完成如下工作

  • 初始化 Spring 容器;
  • 自动配置 Spring Boot 应用的基本功能,如数据库连接、Web 服务器、安全性等;
  • 扫描并注册 Spring 组件到 Spring 容器。

@SpringBootConfiguration

@SpringBootConfiguration 继承自 @Configuration 注解,表明该类是一个 Spring 配置类,可以包含 @Bean 注解的方法,用于定义 Spring 容器中的 Bean。

@EnableAutoConfiguration

@EnableAutoConfiguration 开启了 Spring Boot 的自动配置功能。Spring Boot 根据类路径中的依赖来自动配置 Bean,极大地简化了项目配置,实现开箱即用的效果。

@ComponentScan

@ComponentScan 默认会对当前包及其子包下的所有组件进行扫描,包括标记为 @Component、@Service、@Repository、@Controller 的类,以及其他带有 stereotype 注解的类,将其注册到 Spring 容器中。