首页 > 其他分享 >springboot关键注解

springboot关键注解

时间:2024-05-31 16:01:01浏览次数:13  
标签:springboot Spring void class 关键 import 注解 public

目录

标记容器类注解

1. @Controller

 2. @Service

3. @Repository

4. @Component 

依赖注入注解

1. @Autowired

2. @Resource

@Autowired 与 @Resource 的区别

 web相关注解

@RequestMapping

属性介绍

用法示例

注意事项

@GetMapping 和 @PostMapping

 @RestController

特点

@ControllerAdvice 和 @ExceptionHandler 

@ControllerAdvice

@ExceptionHandler

后端参数接受有关注解

Aop切面有关的注解

1. @Aspect

2 .@After

3. @Before

4. @Around

5. @PointCut

总结

测试常用的注解

1. @SpringBootTest

2. @Test

3. @RunWith

4. 其他JUnit测试注解

总结

一些常见的注解

1. @SpringBootApplication

2. @EnableAutoConfiguration

3. @Configuration

4. @ComponentScan

事务和缓存注解

5. @Transactional

6. @Cacheable

配置和异步任务注解

7. @PropertySource

8. @Async

9. @EnableAsync

10. @EnableScheduling

11. @Scheduled


标记容器类注解

通过使用这些注解,Spring能够自动扫描并管理这些组件,实现松耦合和更清晰的代码结构。

1. @Controller

@Controller注解用于标注控制层组件,也就是MVC(Model-View-Controller)中的Controller层。被@Controller注解的类通常负责处理用户的请求,并将相应的模型数据返回给视图进行展示。Spring的DispatcherServlet会自动扫描并识别这些注解的类,然后将HTTP请求映射到标注了@RequestMapping的方法上。

@Controller
public class MyController {

    @RequestMapping("/home")
    public String home() {
        // 处理请求
        return "home"; // 返回视图名
    }
}

 2. @Service

@Service注解用于标注服务层组件,也就是业务逻辑层的类。它的主要目的是将业务逻辑代码与其他代码(例如控制层和数据访问层)分离。被@Service注解的类通常包含业务逻辑方法,这些方法可以调用数据访问层的代码来获取和处理数据。

@Service
public class MyService {

    public void performBusinessLogic() {
        // 业务逻辑代码
    }
}

3. @Repository

@Repository注解用于标注数据访问层组件,也就是DAO(Data Access Object)层的类。它通常用于将数据从数据库中读取或写入数据库中。@Repository注解还有一个额外的功能:Spring会将数据访问层的异常转换为Spring的数据访问异常(DataAccessException)。

@Repository
public class MyRepository {

    public List<MyEntity> findAll() {
        // 数据访问代码
    }
}

4. @Component 

@Component注解用于标注一个通用的Spring管理组件。它是一个通用的注解,意味着可以将任何类标注为Spring的组件,使其被Spring容器管理。@Component也是一个元注解,意味着其他注解(如@Controller@Service@Repository)都是基于@Component的特化形式。

@Component
public class MyComponent {

    public void doSomething() {
        // 一些通用操作
    }
}

依赖注入注解

1. @Autowired

@Autowired注解是Spring框架提供的,用于自动注入依赖对象。它可以用在构造器、Setter方法或字段上。默认情况下,@Autowired按类型(byType)进行自动注入。如果Spring容器中存在多个相同类型的bean,可以结合@Qualifier注解按名称(byName)进行注入。

  • 按类型注入(byType):Spring容器会根据需要注入的bean类型,查找匹配的bean并注入。
  • 按名称注入(byName):可以与@Qualifier注解结合使用,指定注入的bean的名称。
@Component
public class MyService {

    @Autowired
    private MyRepository myRepository; // 按类型注入

    @Autowired
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository; // 按类型注入
    }

    @Autowired
    public void setMyRepository(MyRepository myRepository) {
        this.myRepository = myRepository; // 按类型注入
    }
}

2. @Resource

@Resource注解是JDK标准的注解(来自javax.annotation包),它也可以用于依赖注入。@Resource注解默认按名称(byName)进行注入,如果没有指定名称则按类型(byType)进行注入。它具有两个重要属性:nametype

  • name属性:指定要注入的bean的名称。
  • type属性:指定要注入的bean的类型。

装配顺序:

  1. 如果同时指定了nametype,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个都会抛出异常。
  4. 如果既没有指定name又没有指定type,则默认按名称(byName)方式进行装配;如果没有匹配,则回退为按类型(byType)进行装配,如果匹配则自动装配。
@Component
public class MyService {

    @Resource(name = "myRepository")
    private MyRepository myRepositoryByName; // 按名称注入

    @Resource(type = MyRepository.class)
    private MyRepository myRepositoryByType; // 按类型注入

    @Resource
    private MyRepository myRepository; // 按名称注入(如果名称匹配失败,则按类型注入)
}

@Autowired 与 @Resource 的区别

  1. 默认注入方式

    • @Autowired:默认按类型(byType)注入。
    • @Resource:默认按名称(byName)注入,如果名称匹配失败,则按类型(byType)注入。
  2. 属性配置

    • @Autowired:可以与@Qualifier结合使用来指定按名称注入。
    • @Resource:具有两个属性nametype,可以通过配置这两个属性来控制注入方式。
  3. 应用场景

    • @Autowired:推荐在Spring应用中使用,因为它是Spring提供的注解,功能更加强大和灵活。
    • @Resource:更适用于需要与其他Java EE技术集成的场景,因为它是JDK标准的注解。

 web相关注解

@RequestMapping

@RequestMapping注解是Spring MVC中用于映射Web请求到处理类和处理方法的核心注解。它可以应用在控制器类和方法上,用于定义URL路径、HTTP请求方法、请求参数、请求头等信息

属性介绍
  • value:定义请求的路径。可以是单个路径或路径数组。
  • method:指定处理请求的方法类型,如GETPOSTPUTDELETE等。默认处理所有类型的HTTP请求。
  • produces:定义返回的媒体类型和字符集,通常用于指定响应的Content-Type,例如"application/json""text/html;charset=UTF-8"等。
  • consumes:定义可接受的媒体类型,通常用于指定请求的Content-Type。
  • params:指定请求必须包含的一组参数。
  • headers:指定请求必须包含的一组HTTP头。
用法示例
  1. 注解在类上:当@RequestMapping注解在类上时,所有该类中的处理方法的URL路径都会以类上定义的路径为前缀。
  2. 注解在方法上:方法上的@RequestMapping路径会继承类上的路径,同时可以定义自己的路径和其他属性。
@Controller
@RequestMapping("/api")
public class MyController {

    @RequestMapping(value = "/home", method = RequestMethod.GET)
    public String home() {
        // 处理GET请求 "/api/home"
        return "home"; // 返回视图名
    }

    @RequestMapping(value = "/submit", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String submit(@RequestParam("data") String data) {
        // 处理POST请求 "/api/submit"
        return "{\"status\":\"success\"}"; // 返回JSON数据
    }
}
注意事项
  • 路径继承:类上的路径和方法上的路径会进行拼接。例如,类上的路径是/api,方法上的路径是/home,那么实际处理的路径是/api/home
  • 请求方法method属性指定的请求方法类型非常重要,可以避免由于处理不同请求类型的逻辑混淆而导致的问题。
  • 媒体类型和字符集:使用produces属性可以确保返回的响应符合预期的格式和编码,避免乱码等问题。
@GetMapping 和 @PostMapping

@GetMapping@PostMapping@RequestMapping的简化版本,分别用于处理GET和POST请求。

  • @GetMapping:等同于@RequestMapping(method = RequestMethod.GET)
  • @PostMapping:等同于@RequestMapping(method = RequestMethod.POST)
@Controller
@RequestMapping("/api")
public class MyController {

    @GetMapping("/home")
    public String home() {
        // 处理GET请求 "/api/home"
        return "home"; // 返回视图名
    }

    @PostMapping("/submit")
    @ResponseBody
    public String submit(@RequestParam("data") String data) {
        // 处理POST请求 "/api/submit"
        return "{\"status\":\"success\"}"; // 返回JSON数据
    }
}

 @RestController

@RestController是一个组合注解,它结合了@Controller@ResponseBody。使用@RestController注解的类被Spring处理为一个控制器,且类中所有方法默认返回数据而不是视图页面。

特点
  1. 组合注解

    • @RestController相当于@Controller@ResponseBody两个注解的组合。
    • 适用于开发只与页面进行数据交互的控制层。
  2. 自动添加@ResponseBody

    • 使用@RestController后,类中所有方法的返回值都会被自动转换为JSON或XML格式的响应数据。
    • 无需在每个方法上单独添加@ResponseBody注解。
@RestController
@RequestMapping("/api")
public class MyRestController {

    @GetMapping("/data")
    public MyData getData() {
        return new MyData("example", 123);
    }

    @PostMapping("/submit")
    public Response submitData(@RequestBody MyData data) {
        // 处理提交的数据
        return new Response("success");
    }
}

@ControllerAdvice 和 @ExceptionHandler 

通过这两个注解来定义全局注解,让spring的异常处理能跟其他数据的返回一致,前端才可以统一处理这些

@ControllerAdvice

@ControllerAdvice注解用于定义全局的异常处理、数据绑定、数据格式化和数据预处理。它通常用于声明一个控制器建言,增强整个应用程序中的控制器。

  • 作用:全局控制器增强,用于定义全局的异常处理、数据绑定等逻辑。
  • 自动注册@ControllerAdvice本质上是一个@Component注解,会自动被Spring扫描并注册为一个Bean。
@ExceptionHandler

@ExceptionHandler注解用于方法上,定义特定的异常处理逻辑。通过value属性可以指定需要处理的异常类型。

  • 作用:定义方法来处理特定的异常类型。
  • 结合@ControllerAdvice:可以在全局控制器增强类中使用@ExceptionHandler来处理全局异常。
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<String> handleException(Exception e) {
        return new ResponseEntity<>("An error occurred: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(value = NullPointerException.class)
    public ResponseEntity<String> handleNullPointerException(NullPointerException e) {
        return new ResponseEntity<>("Null pointer exception: " + e.getMessage(), HttpStatus.BAD_REQUEST);
    }
}

@RestController
@RequestMapping("/api")
public class MyRestController {

    @GetMapping("/data")
    public MyData getData() {
        if (true) { // 模拟异常
            throw new NullPointerException("Null value found");
        }
        return new MyData("example", 123);
    }

    @PostMapping("/submit")
    public Response submitData(@RequestBody MyData data) {
        // 处理提交的数据
        return new Response("success");
    }
}

后端参数接受有关注解

可以参考往期文章

spring框架后端接收前端参数的方法-CSDN博客

Aop切面有关的注解

Spring AOP(Aspect-Oriented Programming)允许我们将横切关注点(如日志记录、事务管理、安全性等)从业务逻辑中分离出来。以下是常用的AOP注解及其作用:

1. @Aspect

@Aspect注解用于声明一个类为切面类。切面类包含了通知(Advice)和切点(PointCut)。

@Aspect
@Component
public class MyAspect {
    // 切面类
}
2 .@After

@After注解用于声明后置通知,表示在目标方法执行后执行的逻辑。

@Aspect
@Component
public class MyAspect {

    @After("execution(* com.example.service.*.*(..))")
    public void afterAdvice(JoinPoint joinPoint) {
        System.out.println("After method: " + joinPoint.getSignature());
    }
}
3. @Before

@Before注解用于声明前置通知,表示在目标方法执行前执行的逻辑。

@Aspect
@Component
public class MyAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature());
    }
}
4. @Around

@Around注解用于声明环绕通知,表示在目标方法执行前后都执行的逻辑。环绕通知可以完全控制目标方法的执行。

@Aspect
@Component
public class MyAspect {

    @Around("execution(* com.example.service.*.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("Before method: " + proceedingJoinPoint.getSignature());
        Object result = proceedingJoinPoint.proceed(); // 执行目标方法
        System.out.println("After method: " + proceedingJoinPoint.getSignature());
        return result;
    }
}
5. @PointCut

@PointCut注解用于声明切点,定义拦截规则,确定哪些方法会被切入。切点表达式可以与通知配合使用,以指定在哪些方法上应用通知。

@Aspect
@Component
public class MyAspect {

    @PointCut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {
        // 定义一个切点,指示匹配com.example.service包下的所有方法
    }

    @Before("serviceMethods()")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature());
    }
}

总结

  • @Aspect:声明一个类为切面类。
  • @After:声明后置通知,在目标方法执行后执行。
  • @Before:声明前置通知,在目标方法执行前执行。
  • @Around:声明环绕通知,在目标方法执行前后执行。
  • @PointCut:声明切点,定义拦截规则,确定哪些方法会被切入。

 完整例子,判断登录逻辑

package com.imooc.pan.server.common.aspect;

import com.imooc.pan.cache.core.constants.CacheConstants;
import com.imooc.pan.core.response.R;
import com.imooc.pan.core.response.ResponseCode;
import com.imooc.pan.core.utils.JwtUtil;
import com.imooc.pan.server.common.annotation.LoginIgnore;
import com.imooc.pan.server.common.utils.UserIdUtil;
import com.imooc.pan.server.modules.user.constants.UserConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * 统一的登录拦截校验切面逻辑实现类
 */
@Component
@Aspect
@Slf4j
public class CommonLoginAspect {

    /**
     * 登录认证参数名称
     */
    private static final String LOGIN_AUTH_PARAM_NAME = "authorization";

    /**
     * 请求头登录认证key
     */
    private static final String LOGIN_AUTH_REQUEST_HEADER_NAME = "Authorization";

    /**
     * 切点表达式
     */
    private final static String POINT_CUT = "execution(* com.imooc.pan.server.modules.*.controller..*(..))";

    @Autowired
    private CacheManager cacheManager;

    /**
     * 切点模版方法
     */
    @Pointcut(value = POINT_CUT)
    public void loginAuth() {

    }

    /**
     * 切点的环绕增强逻辑
     * 1、需要判断需不需要校验登录信息
     * 2、校验登录信息:
     * a、获取token 从请求头或者参数
     * b、从缓存中获取token,进行比对
     * c、解析token
     * d、解析的userId存入线程上下文,供下游使用
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("loginAuth()")
    public Object loginAuthAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        if (checkNeedCheckLoginInfo(proceedingJoinPoint)) {
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = servletRequestAttributes.getRequest();
            String requestURI = request.getRequestURI();
            log.info("成功拦截到请求,URI为:{}", requestURI);
            if (!checkAndSaveUserId(request)) {
                log.warn("成功拦截到请求,URI为:{}. 检测到用户未登录,将跳转至登录页面", requestURI);
                return R.fail(ResponseCode.NEED_LOGIN);
            }
            log.info("成功拦截到请求,URI为:{},请求通过", requestURI);
        }
        
        return proceedingJoinPoint.proceed();
    }

    /**
     * 校验token并提取userId
     *
     * @param request
     * @return
     */
    private boolean checkAndSaveUserId(HttpServletRequest request) {
        String accessToken = request.getHeader(LOGIN_AUTH_REQUEST_HEADER_NAME);
        if (StringUtils.isBlank(accessToken)) {
            accessToken = request.getParameter(LOGIN_AUTH_PARAM_NAME);
        }
        
        if (StringUtils.isBlank(accessToken)) {
            return false;
        }
        Object userId = JwtUtil.analyzeToken(accessToken, UserConstants.LOGIN_USER_ID);
        if (Objects.isNull(userId)) {
            return false;
        }

        Cache cache = cacheManager.getCache(CacheConstants.R_PAN_CACHE_NAME);
        String redisAccessToken = cache.get(UserConstants.USER_LOGIN_PREFIX + userId, String.class);

        if (StringUtils.isBlank(redisAccessToken)) {
            return false;
        }

        if (Objects.equals(accessToken, redisAccessToken)) {
            saveUserId(userId);
            return true;
        }

        return false;
    }

    /**
     * 保存用户ID到线程上下文中
     *
     * @param userId
     */
    private void saveUserId(Object userId) {
        UserIdUtil.set(Long.valueOf(String.valueOf(userId)));
    }

    /**
     * 校验是否需要校验登录信息
     *
     * @param proceedingJoinPoint
     * @return true 需要校验登录信息 false 不需要
     */
    private boolean checkNeedCheckLoginInfo(ProceedingJoinPoint proceedingJoinPoint) {
        Signature signature = proceedingJoinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        return !method.isAnnotationPresent(LoginIgnore.class);
    }


}

测试常用的注解

Spring Boot 提供了一组强大的测试注解和工具,使得编写和运行测试变得更加简便和高效。以下是常用的测试注解及其作用。

1. @SpringBootTest

@SpringBootTest注解用于在测试环境中启动整个Spring上下文。

  • 作用:在测试中启动Spring应用程序上下文,并进行集成测试。
@SpringBootTest
public class MyApplicationTests {

    @Test
    public void contextLoads() {
        // 测试上下文加载
    }
}
2. @Test

@Test注解用于将一个普通方法标记为测试方法,这是JUnit提供的基本注解。

  • 作用:标记一个方法为测试方法。
@Test
public void testMethod() {
    // 测试方法
}
3. @RunWith

@RunWith注解用于指定测试运行器,Spring Boot 集成了JUnit。

  • 作用:指定测试类运行的运行器。
  • 常用运行器
    • SpringJUnit4ClassRunner.class
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyApplicationTests {

    @Test
    public void contextLoads() {
        // 测试上下文加载
    }
}
4. 其他JUnit测试注解
  1. @Ignore:忽略测试方法,测试时不会运行此方法。
@Test
@Ignore("Not ready yet")
public void ignoredTest() {
    // 测试方法将被忽略
}

@Before:在每个测试方法之前运行

@After:在每个测试方法之后运行。

@Before
public void setUp() {
    // 测试前初始化
}

  1. @BeforeClass:在所有测试方法之前运行一次,必须是静态方法。
  2. @AfterClass:在所有测试方法之后运行一次,必须是静态方法。
@BeforeClass
public static void setUpBeforeClass() {
    // 测试前初始化
}

总结

  • @SpringBootTest:用于启动Spring应用程序上下文,进行集成测试。
  • @Test:标记一个方法为测试方法。
  • @RunWith:指定测试运行器,常用于整合JUnit和Spring测试框架。
  • @Ignore@Before@After@BeforeClass@AfterClass:JUnit提供的注解,用于管理测试方法的执行顺序和状态。
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyApplicationTests {

    @BeforeClass
    public static void initAll() {
        // 初始化所有测试前运行
        System.out.println("BeforeClass: 初始化所有测试前运行");
    }

    @Before
    public void init() {
        // 初始化每个测试前运行
        System.out.println("Before: 初始化每个测试前运行");
    }

    @Test
    public void contextLoads() {
        // 测试上下文加载
        System.out.println("Test: 测试上下文加载");
    }

    @Test
    public void anotherTest() {
        // 另一个测试方法
        System.out.println("Test: 另一个测试方法");
    }

    @Ignore("Test is ignored as a demonstration")
    @Test
    public void ignoredTest() {
        // 被忽略的测试方法
        System.out.println("Ignore: 这个测试方法将被忽略");
    }

    @After
    public void tearDown() {
        // 每个测试后运行
        System.out.println("After: 每个测试后运行");
    }

    @AfterClass
    public static void tearDownAll() {
        // 所有测试后运行
        System.out.println("AfterClass: 所有测试后运行");
    }
}

一些常见的注解

1. @SpringBootApplication

@SpringBootApplication 是 Spring Boot 的核心注解,用于标注一个主程序类,启动 Spring Boot 应用。它是一个组合注解,包含了以下三个注解:

  • @Configuration:标记一个类为配置类。
  • @EnableAutoConfiguration:启用 Spring Boot 的自动配置机制。
  • @ComponentScan:启用组件扫描。
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
2. @EnableAutoConfiguration

@EnableAutoConfiguration 自动加载符合条件的配置类,以便 Spring 应用程序根据类路径中的依赖和自定义配置自动配置 Spring 应用程序。

3. @Configuration

@Configuration 用于定义配置类,该类可以包含 Spring bean 定义

@Configuration
public class MyConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}
4. @ComponentScan

@ComponentScan 用于自动扫描指定包及其子包中的 Spring 组件(如 @Component、@Service、@Controller、@Repository 等)。

@ComponentScan(basePackages = "com.example")
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

事务和缓存注解

5. @Transactional

@Transactional 用于声明事务,确保方法运行在事务上下文中。

@Service
public class MyService {
    @Transactional
    public void performTransaction() {
        // 事务操作
    }
}
6. @Cacheable

@Cacheable 用于声明缓存,方法的返回值会被缓存起来。

@Service
public class MyService {
    @Cacheable("myCache")
    public MyData getData(String id) {
        return myRepository.findById(id);
    }
}

配置和异步任务注解

7. @PropertySource

@PropertySource 用于引入外部属性文件到 Spring 环境中。

@Configuration
@PropertySource("classpath:application.properties")
public class MyConfig {
}
8. @Async

@Async 用于标识异步方法,方法会在独立的线程中执行。

@Service
public class MyService {
    @Async
    public void asyncMethod() {
        // 异步操作
    }
}
9. @EnableAsync

@EnableAsync 用于开启异步方法支持,通常用于配置类上。

10. @EnableScheduling

@EnableScheduling 用于开启计划任务的支持,通常用于配置类上。

11. @Scheduled

@Scheduled 用于声明计划任务方法,可以设置任务的执行时间和频率。

@Service
public class MyService {
    @Scheduled(cron = "0 0 * * * ?")
    public void scheduledTask() {
        // 计划任务操作
    }
}

标签:springboot,Spring,void,class,关键,import,注解,public
From: https://blog.csdn.net/weixin_64122713/article/details/139347226

相关文章