Spring Boot 注解详解

Ubanillx 发布于 26 天前 49 次阅读


本文采取分类的方式进行注解讲解,方便记忆,对于比较容易混淆的注解,给与了实例讲解,希望对你会有帮助。

一、web mvc开发时,对于三层的类注解

1.1 @Controller

应用在MVC层(控制层),DispatcherServlet会自动扫描注解了此注解的类,然后将web请求映射到注解了@RequestMapping的方法上。

1.2 @Service

应用在service层(业务逻辑层)

1.3 @Reponsitory

应用在dao层(实现类)(数据访问层)

1.4 @component

表示一个带注释的类是一个“组件”,成为Spring管理的Bean。当使用基于注解的配置和类路径扫描时,这些类被视为自动检测的候选对象。同时@Component还是一个元注解。

注意: @Controller、@Service、@Reponsitory都组合了 @Component注解。为了区分三层不同的作用,因此分别为三层起了不同的名字。

二、依赖注入的注解

依赖注入有那种方式,@Resource是jdk中的,@Autowired是spring的,两个都可以注入一个java bean。

2.1@Autowired

由Spring的依赖注入工具(BeanPostProcessor、BeanFactoryPostProcessor)自动注入,Spring提供的工具。这个注解是最常用的注解,请切记!

2.2 @Resource

依赖注入,给对象的属性注入数据,可以定义在字段上,也可以定义在方法上。一般用在注入dao层数据源,跟@Autowired相似,区别就是@Autowired默认是先根据类型,而@Resource默认是先根据名称

2.3 @Resource、@Autowired的区别

根据类型或者名称进行依赖注入,这又是什么意思呢 ? 有些小伙伴可能还不知道,下面介绍一下:

@Resource的作用相当于@Autowired,只不过@AutowiredbyType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是nametypeSpring@Resource注解的name属性解析为bean的名字,而type属性则解析为code>bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
  @Resource装配顺序
  1. 如果同时指定了nametype,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

这么长篇大论,可能你还是晕,下面我们用一个范例来讲解给你听:

2.3.1 实例讲解(错误实例)

新建Animal接口类
package com.ieslab.powergrid.demosvr.entity;

import org.springframework.stereotype.Component;

/**
* 动物接口类
*/

@Component
public interface Animal {
public void walk();
}
新建两个实现类Cat.java 和 Dog.java

这两个实现类都实现了walk()方法,但是执行内容不同,我们用打印日志不同区分一下。

package com.ieslab.powergrid.demosvr.entity;

import org.springframework.stereotype.Component;

@Component
public class Cat implements Animal{
@Override
public void walk() {
System.out.println("cat walk");
}
}
package com.ieslab.powergrid.demosvr.entity;

import org.springframework.stereotype.Component;

@Component
public class Dog implements Animal{
@Override
public void walk() {
System.out.println("dog walk");
}
}
编写测试用例
package com.ieslab.powergrid.demosvr.entity;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest
class AnimalTest {
@Autowired
Animal animal;

@Test
void test(){
animal.walk();
}
}

这个测试用例,我们使用@AutowiredAnimal animal;进行依赖注入,我么知道@Autowired是根据类型进行注入的,这时候的类型就是Animal ,但是依赖注入是,是根据具体实现进行注入的,而且具体实现只能有一个时,他才能知道注入哪一个实现类,因此,此处这样写一定会报错,我们执行一下看看吧。
在这里插入图片描述
报错的地方给我们提示了:but found 2: Cat,Dog,思是Animal有两个实现类。解决方案如下:

  1. 还是使用@Autowired 注解,但是我们需要为其设置具体的实现类型,这是就需要一个新的注解:@Qualifier,如下图修改代码:
    在这里插入图片描述
  2. 使用@Resource 注解,但是我们需要为其设置具体的实现的名称,如下代码:
package com.ieslab.powergrid.demosvr.entity;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;

@SpringBootTest
class AnimalTest2 {
@Resource(name="cat") //注意是cat不是cat,因为使用@Service,容器为我们创建bean时默认类名首字母小写
Animal animal;
@Test
void test(){
animal.walk();
}
}

2.4 @Value

由于@Autowired、@Qualifier、@Resource三者自动装配只能针对于注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。因此有了@Value这个注解,@Value专门用来服务基本类型和String类型。

另外@Value注解有一个value 属性:用于指定数据的值。它可以使用spring中SpEL(也就是spring的EL表达式)。SpEL的写法:${表达式},当然也可以类似mybatis中的 #{表达式} 的写法

@Value("#{2*3}")  //#写法 表示6
private int age;

@Value("178")    //普遍写法 178
private int height;

@Value("${man.weight}")  //SpEL的写法一般操作配置文件中数据
private int weight;

总结:通过@Value注解将常量、配置文件中的值、其他bean的属性值注入到变量中,作为变量的初始值。支持表达式、直接赋值、配置文件三种方式。

2.5 @Data

有时候你会遇到@Data注解,其实这个注解和lombok插件有关,@Data 注解的主要作用是提高代码的简洁,使用这个注解可以省去代码中大量的get()、 set()、 toString()等方法;

三、WEB 常用的注解

3.1 @RequestMapping

用来映射web请求(访问路径和参数),处理类和方法的。可以注解在类和方法上,注解在方法上的@RequestMapping路径会继承注解在类上的路径。同时支持Serlvetrequestresponse作为参数,也支持对requestresponse的媒体类型进行配置。其中有value(路径),produces(定义返回的媒体类型和字符集),method(指定请求方式)等属性。

注意
@GetMapping和@PostMapping@RequestMapping的两种特例,一个是get方式请求,一个是post方式,此处不再描述。

3.2 @RequestParam

@RequestParam:将请求参数绑定到你控制器的方法参数上(是springmvc中接收普通参数的注解)
3.2.1 语法
语法1:
@RequestParam(value=”参数名”,required=”true/false”,defaultValue=””)
value:参数名

required:是否包含该参数,默认为true,表示该请求路径中必须包含该参数,如果不包含就报错。

defaultValue:默认参数值,如果设置了该值,required=true将失效,自动为false,如果没有传该参数,
就使用默认值

语法2:
@RequestParam("参数名")
3.2.2 实例
package com.ieslab.powergrid.demosvr.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/api")
public class TestController {
/**
* 接收普通请求参数
* http://localhost:8080/api/test1?name=liu
* url参数中的name必须要和@RequestParam("name")一致,
* 因为请求参数绑定到你控制器的方法参数,所以方法参数可以自定义
*/

@RequestMapping("/test1")
@ResponseBody
public String test1(@RequestParam("name")String name1){
System.out.println(name1);
return name1;
}

/**
* 接收普通请求参数
* http://localhost:8080/api/test2?name=lin
* url参数中的name必须要和@RequestParam("name")一致
* url中没有name参数不会报错、有就显示出来
*/

@RequestMapping("/test2")
@ResponseBody
public String test2(@RequestParam(value="name",required=false)String name2){
System.out.println(name2);
return name2;
}

/**
* 接收普通请求参数
* http://localhost:8080/api/test3?name=zhang 显示为zhang
* http://localhost:8080/api/test3?name 显示为hello,此时设置了默认值
*/

@RequestMapping("/test3")
@ResponseBody
public String test3(@RequestParam(value="name",required=true,defaultValue="hello")String name3){
System.out.println(name3);
return name3;
}
}

注意: url中请求的参数名称一定要和@RequestParam(value="")中value的值保持一致。
实例中的三个案例的注释讲的很清楚,请仔细看看。

3.3 @PathVariable

@PathVariable 放置在参数前,用来接受路径参数。

@RequestMapping(value = "user/{username}")
public String test(@PathVariable(value="username") String username) {
	return "user"+username;
}

这里的{username}就是我们定义的变量规则,username是变量的名字, 注解@PathVariable(value=“username”) String username 会获取变量的值为方法中的参数赋值。

3.4 @RequestParam和@PathVariable区别

前者是在url中以参数方式传输,后者在请求url路径中根据变量传输,二者的应用场景建议如下:

1、当URL指向的是某一具体业务资源(或资源列表),例如个人博客或者用户时,使用@PathVariable
2、当URL需要对资源或者资源列表进行过滤,筛选时,用@RequestParam

例如我们会这样设计URL:

/blogs/{blogId}
/blogs?state=publish
而不是/blogs/state/publish来表示处于发布状态的博客文章

3.5 @ResponseBody和@RequestBody

@ResponseBody:将返回值放在response体内。返回的是数据而不是页面。在异步请求返回json数据时使用。
@RequestBody:允许request的参数在request体中,而不是在直接链接在地址的后面。此注解放置在参数前。比如:直接以String接收前端传过来的json数据:

/***
* 直接以String接收前端传过来的json数据
*
* @Param str:json格式的字符串
* @return: json格式的字符串
**/

@PostMapping("/test")
@ResponseBody
public String test(@RequestBody String str){
return str;
}

3.6 @RestController

1)组合注解,组合了@Controller@ResponseBody,当我们只开发一个和页面交互数据的控制层的时候可以使用此注解。
2)使用此注解后,在方法层就不用添加@ResponseBody注解了,并且这个类中所有的方法都默认添加了@ResponseBody注解,都返回的是数据而不是界面。

3.7 @ControllerAdvice和@ExceptionHandler

@ControllerAdvice用在类上,声明一个控制器建言,它也组合了@Component注解,会自动注册为Spring的Bean。
ExceptionHandler用在方法上定义全局处理,通过他的value属性可以过滤拦截的条件:@ExceptionHandler(value=Exception.class)–表示拦截所有的Exception。
应用场景:统一异常处理:下面大概介绍一下,详细了解请查看本人写的文章:Springboot:统一异常处理:https://blog.csdn.net/houpeibin2012/article/details/104440752

四、Spring Boot 常用的注解

4.1 @SpringBootApplication:启动

SpringBoot 的核心注解,主要目的是开启自动配置。它也是一个组合注解,主要组合了 @Configuration,@EnableAutoConfiguration(核心)和 @ComponentScan。可以通过 @SpringBootApplication (exclude={想要关闭的自动配置的类名.class}) 来关闭特定的自动配置,其中 @ComponentScan 让 Spring Boot 扫描到 Configuration 类并把它加入到程序上下文。

示例

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

4.2 @EnableAutoConfiguration: 自动配置

此注释自动载入应用程序所需的所有 Bean —— 这依赖于 Spring Boot 在类路径中的查找。该注解组合了 @Import 注解,@Import 注解导入了 EnableAutoConfigurationImportSelector 类,它使用 SpringFactoriesLoader.loaderFactoryNames 方法来扫描具有 META-INF/spring.factories 文件的 jar 包,而 spring.factories 里声明了有哪些自动配置。

示例

@Configuration
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class AppConfig {
    // 自定义配置
}

4.3 @Configuration:配置文件

等同于 Spring 的 XML 配置文件;使用 Java 代码可以检查类型安全。

示例

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

4.4 @ComponentScan:自动扫描

表示将该类自动发现扫描组件。如果扫描到有 @Component、@Controller、@Service 等这些注解的类,并注册为 Bean,可以自动收集所有的 Spring 组件,包括 @Configuration 类。

示例

@Configuration
@ComponentScan(basePackages = "com.example.service")
public class AppConfig {
    // 配置类
}

五、AOP 常用的注解

5.1 @Aspect:切面

声明一个切面。

示例

@Aspect
@Component
public class LoggingAspect {
    // 切面逻辑
}

5.2 @After:后置建言

后置建言(advice),在原方法后执行。

示例

@After("execution(* com.example.service.*.*(..))")
public void afterAdvice(JoinPoint joinPoint) {
    System.out.println("方法执行后: " + joinPoint.getSignature().getName());
}

5.3 @Before:前置建言

前置建言(advice),在原方法前执行。

示例

@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
    System.out.println("方法执行前: " + joinPoint.getSignature().getName());
}

5.4 @Around:环绕

环绕建言(advice),在原方法执行前执行,在原方法执行后再执行(@Around 可以实现其他两种 advice)。

示例

@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("方法执行前");
    Object result = joinPoint.proceed();
    System.out.println("方法执行后");
    return result;
}

5.5 @Pointcut:切点

声明切点,即定义拦截规则,确定有哪些方法会被切入。

示例

@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}

六、测试常用的注解

6.1 @SpringBootTest

@SpringBootTest 注解是 SpringBoot Since:1.4.0 版本开始引入的一个用于测试的注解。

示例

@SpringBootTest
class MyServiceTest {
    @Autowired
    private MyService myService;

    @Test
    void testMyService() {
        // 测试逻辑
    }
}

6.2 @Test

将一个普通方法修饰为一个测试方法。

示例

@Test
void testAddition() {
    assertEquals(4, 2 + 2);
}

6.3 @RunWith

这个是 Junit 的注解,SpringBoot 集成了 Junit。一般在测试类里使用: @RunWith (SpringJUnit4ClassRunner.class) —— SpringJUnit4ClassRunner 在 JUnit 环境下提供 Spring TestContext Framework 的功能,最主要是声明测试的运行器,都在 org.junit.runners 下。@RunWith (SpringRunner.class),表明这个类中的测试用例需要使用 SpringRunner 类来执行。

示例

@RunWith(SpringRunner.class)
@SpringBootTest
class MyServiceTest {
    // 测试类
}

6.4 其他测试注解

  1. @Ignore : 被忽略的测试方法
  2. @Before: 每一个测试方法之前运行
  3. @After : 每一个测试方法之后运行
  4. @BeforeClass: 所有测试开始之前运行
  5. @AfterClass: 所有测试结束之后运行

示例

@RunWith(SpringRunner.class)
@SpringBootTest
class MyServiceTest {
    @Before
    public void setUp() {
        // 初始化测试环境
    }

    @After
    public void tearDown() {
        // 清理测试环境
    }

    @Test
    void testMethod() {
        // 测试逻辑
    }
}

七、其他注解:都是比较常用的

7.1 @Transactional:事务声明

声明事务(一般默认配置即可满足要求,当然也可以自定义)。

示例

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Transactional
    public void createUser(User user) {
        userRepository.save(user);
    }
}

7.2 @Cacheable:缓存

声明数据缓存。

示例

@Service
public class ProductService {
    @Cacheable("products")
    public Product getProductById(Long id) {
        // 从数据库获取产品
    }
}

7.3 @PropertySource:文件引入

指定文件地址。提供了一种方便的、声明性的机制,用于向 Spring 的环境添加 PropertySource。与 @Configuration 类一起使用。

示例

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {
    @Value("${database.url}")
    private String dbUrl;
}

7.4 @Async:多线程异步方法

注解在方法上标示这是一个异步方法,在类上标示这个类所有的方法都是异步方法。

示例

@Service
public class EmailService {
    @Async
    public void sendEmail(String to, String subject, String body) {
        // 异步发送邮件
    }
}

7.5 @EnableAsync:多线程

开启异步任务支持。注解在配置类上。

示例

@Configuration
@EnableAsync
public class AppConfig {
    @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(25);
        executor.initialize();
        return executor;
    }
}

7.6 @EnableScheduling:开启计划任务

注解在配置类上,开启对计划任务的支持。

示例

@Configuration
@EnableScheduling
public class AppConfig {
    // 配置类
}

7.7 @Scheduled:计划任务

注解在方法上,声明该方法是计划任务。支持多种类型的计划任务:cron, fixDelay, fixRate。

示例

@Service
public class ScheduledService {
    @Scheduled(fixedRate = 5000) // 每5秒执行一次
    public void performTask() {
        // 定时执行的任务
    }
}
此作者没有提供个人介绍
最后更新于 2025-05-27