Java开发Spring常见注解

Java开发Spring常见注解

   前言

   Spring注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大提高了开发效率。 下面按照分类讲解Spring中常用的一些注解。

   一、声明bean的注解

   1. @Component

   一个通用的注解,用于标识任何 Spring 组件。标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。

   示例代码如下:

1 @Component
2 public class CallBackAfterCreatePolicyProducer {
3     @Resource
4     private YpProducer ypProducer;
5 }

   说明:

   1)@Component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>

   2)@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

   3)@Component是一个元注解,意思是可以注解其他类注解,如@Controller @Service @Repository @Aspect。官方的原话是:带此注解的类看为组件,当使用基于注解的配置和类路径扫描的时候,这些类就会被实例化。其他类级别的注解也可以被认定为是一种特殊类型的组件,比如@Repository @Aspect。所以,@Component可以注解其他类注解。

   2. @Service

   用于标识服务层组件,主要包含业务逻辑。

   组合注解(组合了@Component注解),应用在service层(业务逻辑层)

1 @Slf4j
2 @Service
3 @RequiredArgsConstructor(onConstructor_ = {@Autowired})
4 public class TppAgencyHttpProxyServiceImpl implements TppAgencyHttpProxyService {
5 }

   3. @Repository

   用于标识数据访问层组件,负责与数据库交互,并提供异常转换功能。

   组合注解(组合了@Component注解),应用在dao层(数据访问层)。

1 @Repository
2 public interface InsuranceAgreementMapper extends MPJBaseMapper<InsuranceAgreementDO> {
3 
7 }

   4. @Mapper

   @Mapper注解是mybatis的注解,是用来说明这个是一个Mapper,对应的xxxMapper.xml就是来实现这个Mapper。然后再server层使用@Autowired注解引用进来,会出现这样的情况,但是并不影响使用。

   

   这是因为@Autowired是spring的注解,提示找不到相应的bean。如果有强迫症的同学,可以使用@Resource注解,因为这个是JDK的注解。

   

   二、注入bean的注解

   1. @Autowired

   @Autowired注解是Spring Framework提供的一种依赖注入方式。可以用于字段、方法和构造函数上,用于指定要注入的依赖。

   示例代码:

1 public class MyService {
2     @Autowired
3     private MyDependency dependency;
4     // ...
5 }
6 ```

   说明:@Autowired注解用于标记要注入的依赖。Spring会根据依赖的类型(或名称和限定符)自动查找匹配的Bean,并将其注入到目标对象中。

   有一点要特别注意:

   使用@Autowired 依赖注入静态成员(属性)。

   分析:静态变量(成员)它是属于类的,而非属于实例对象的属性;同样的静态方法也是属于类的,普通方法(实例方法)才属于对象。而Spring容器管理的都是实例对象,包括它的@Autowired依赖注入的均是容器内的对象实例,所以对于static成员是不能直接使用@Autowired注入的

   比如下面:

 1 @Component
 2 public class SonHolder {
 3 
 4     @Autowired
 5     private static Son son;
 6 
 7     public static Son getSon() {
 8         return son;
 9     }
10 }

   这很容易理解:类成员的初始化较早,并不需要依赖实例的创建,所以这个时候Spring容器可能都还没“出生”,更不要提依赖注入了。

   2. @Resource

   @Resource注解是Java标准库提供的一种依赖注入方式。可以用于字段、方法和构造函数上,用于指定要注入的依赖。

1 public class MyService{
2 @Resource
3 private MyDependency dependency;
4 // ...
5 }

   说明:@Resource注解是Java标准库提供的一种依赖注入方式,在Spring中借助 CommonAnnotationBeanPostProcessor来实现。它可以用于标记要注入的依赖,并根据名称匹配规则或显式指定的名称来查找依赖。

   3. @RequiredArgsConstructor

   @RequiredArgsConstructor 是一个 Lombok 注解,用于自动生成一个带有所有必需参数的构造函数。这个注解可以用在类级别上,会生成一个构造函数,用于初始化被 @NonNull 或者 final 标记的成员变量。

   示例代码:

1 @Slf4j
2 @Service
3 @RequiredArgsConstructor(onConstructor_ = {@Autowired})
4 public class BrowseBizServiceImpl implements BrowseBizService {
5 
6     private final BrowseRpcProxyService browseRpcProxyService;
7 
8 }  

   说明:Spring 提供了几种注入模式,一种是属性注入(Filed injection),一种是通过 Setter 方法,一种是构造器注入。Spring 从 4.0 开始, 就不推荐使用属性注入模式了 ,原因是它可以让我们忽略掉一些代码可能变坏的隐患。

   所以,构造器的方法就成了我们的首选。但是使用构造器注入时,代码会很多。构造器注入通常结合private final字段来使用。使用Lombok的@RequiredArgsConstructor注解可以简化构造器的生成。

   4. @inject:JSR-330提供的注解。

   5. @Resource和@Autowired的区别

   1)区别一:所属不同

   @Autowired 是 spring-beans 模块提供的注解。

   @Resource 是 JSR 250 规范提出的注解,由 JDK 自带。

   2)区别二:装配方式不同。两者都可以标注在属性或 setter 方法上。

  @Autowired 注解默认是按照类型进行自动装配的。

  如果同一个类型的 Bean 有多个实例,那么直接使用 @Autowired 会导致 Spring 无法确定需要注入哪个实例,从而抛出异常。

  此时可以配合 @Qualifier 注解来指定 Bean 名称,以便按名称进行注入。

  所以,当需要按名称装配时,可以在 @Autowired 后面加上 @Qualifier 注解,例如:

@Autowired
@Qualifier("beanName")
private YourBeanType yourBean;

   @Resource 默认依赖 bean 的名称为属性名,并且可以通过其属性 name 进行指定。默认依赖的 bean 的类型为属性的类型,并且可以通过 type 属性进行指定。 如果未指定依赖的 bean 的名称并且属性名对应的 bean 在容器中不存在时才会按照类型进行注入,否则按照名称进行注入依赖。(先按name再按type)

   3)区别三:是否强依赖不同

   @Autowired 指定的依赖默认必须存在,可以通过 required 属性指定不存在。

   示例代码如下:

   @Autowired(required = false)
   private AdminInsuranceEventService adminInsuranceEventService;

   @Resource 指定的依赖必须存在。

   6. @Qualifier 

   通过名称指定需要注入的 Bean,特别是在同一个类型有多个实现的情况下(容器中有多个相同类型的bean)。

   @Qualifier 的值必须与 Bean 的名称一致,通常在 @Component 或 @Bean 中定义。

   1)方式一:假设我们有两个实现类 ServiceA 和 ServiceB,都实现了接口 MyService,如果要注入 ServiceA,可以这样写:

 1 @Component("serviceA")
 2 public class ServiceA implements MyService {
 3     // Implementation
 4 }
 5 
 6 @Component("serviceB")
 7 public class ServiceB implements MyService {
 8     // Implementation
 9 }
10 
11 @Autowired
12 @Qualifier("serviceA")
13 private MyService myService;

   2)方式二:

   配置类中定义@Bean

 1 @Configuration
 2 public class AppConfig {
 3 
 4     @Bean(name = "serviceA")
 5     public MyService myServiceA() {
 6         return new ServiceA();
 7     }
 8 
 9     @Bean(name = "serviceB")
10     public MyService myServiceB() {
11         return new ServiceB();
12     }
13 }

   在需要注入ServiceA的地方,使用 @Qualifier 指定名称:

 1 @Component
 2 public class MyComponent {
 3 
 4     @Autowired
 5     @Qualifier("serviceA")
 6     private MyService myService;
 7 
 8     // 或者使用构造函数注入
 9     // public MyComponent(@Qualifier("serviceA") MyService myService) {
10     //     this.myService = myService;
11     // }
12 }

   当然,也可以用@Resource来注入

 1 import javax.annotation.Resource;
 2 
 3 @Component
 4 public class MyComponent {
 5 
 6     @Resource(name = "serviceA")
 7     private MyService myService;
 8 
 9     // 或者使用构造函数注入方式
10     // public MyComponent(@Resource(name = "serviceA") MyService myService) {
11     //     this.myService = myService;
12     // }
13 }

   7.  @Primary

  当发生依赖注入的歧义时,我们也可以用@Primary注解来决定要注入哪个 bean。当存在多个相同类型的 bean 时,此注解定义了首选项。除非另有说明,否则将使用与 @Primary 注释关联的 bean

  例如:

 1     @Bean
 2     public Employee tomEmployee() {
 3         return new Employee("Tom");
 4     }
 5 
 6     @Bean
 7     @Primary
 8     public Employee johnEmployee() {
 9         return new Employee("john");
10     }

   在此示例中,两个方法都返回相同的 Employee类型。Spring 将注入的 bean 是方法 johnEmployee 返回的 bean。这是因为它包含 @Primary 注解。

   8. @Qualifier 和 @Primary的区别

  当我们想要指定默认情况下应该注入特定类型的 bean 时,@Primary注解很有用。

  如果我们在某个注入点需要另一个 bean,我们需要专门指出它。我们可以通过 @Qualifier 注解来做到这一点。

  值得注意的是,如果 @Qualifier 和 @Primary 注释都存在,那么 @Qualifier 注释将具有优先权。基本上,@Primary 是定义了默认值,而 @Qualifier 则非常具体。

   例如:

 1      @Component
 2      @Primary
 3      public class FooFormatter implements Formatter {
 4          public String format() {
 5              return "foo";
 6          }
 7      }
 8  
 9      @Component
10      public class BarFormatter implements Formatter {
11          public String format() {
12              return "bar";
13          }
14      }

   在这种情况下,@Primary 注解指定了默认注入的是 FooFormatter,消除了场景中的注入歧义。

   三、配置类相关注解

   1. @Configuration

   声明当前类为配置类,相当于xml形式的Spring配置

   示例代码如下:

1 @Configuration
2 @ComponentScan("com.yp")
3 public class SpringConfig {
4 
5 }

   2. @Bean

   注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式

   Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后Spring将会将这个Bean对象放在自己的IOC容器中。

 1 @Configuration
 2 public class AppConfig {
 3 
 4       // 使用@Bean 注解表明myBean需要交给Spring进行管理
 5       // 未指定bean 的名称,默认采用的是 "方法名" + "首字母小写"的配置方式
 6     @Bean
 7     public MyBean myBean(){
 8         return new MyBean();
 9     }
10 }
11 
12 public class MyBean {
13 
14     public MyBean(){
15         System.out.println("MyBean Initializing");
16     }
17 }

   说明:@Bean 更适合在配置类中集中管理 Bean 的创建,适合定义更加灵活或需要初始化逻辑的 Bean。

   3. @ComponentScan 

   配置组件扫描通常使用 @ComponentScan 注解。

   Spring 通过组件扫描机制自动检测并注册带有这些特定注解的类为 Spring Bean。

1 import org.springframework.context.annotation.ComponentScan;
2 import org.springframework.context.annotation.Configuration;
3 
4 @Configuration
5 @ComponentScan(basePackages = "com.example")
6 public class AppConfig {
7     // 其他配置
8 }

   比如:指定了spring扫描的包路径为:com.example,这将说明在此包下的所有spring识别的注解都会被解析

   四、切面(AOP)相关注解

   1. @Aspect
   声明一个切面(类上) 使用@After、@Before、@Around、@AfterReturning、@AfterwThrowing定义通知(advice),可直接将拦截规则(切点)作为参数。

   示例代码如下:

 1 @Component
 2 @Aspect
 3 public class MyAspectjAdvice {
 4 
 5     @Pointcut("execution(* com.yp.dao.BookDao.*(..))")
 6     private void pt() {
 7     }
 8 
 9     /**
10      * 前置通知
11      */
12     @Before("pt()")
13     public void myBefore() {
14         System.out.println("前置通知...");
15     }
16 
17     /**
18      * 后置通知
19      */
20     @After("pt()")
21     public void myAfter() {
22         System.out.println("后置通知...");
23     }
24 }

   2. @Pointcut: 声明切点   

   五、Spring MVC常用注解

   1.  @Controller

   用于标识控制器层组件,处理 HTTP 请求和响应。

   在使用 Spring MVC 框架开发 Web 应用程序时,@Controller 注解是用来标识一个类为控制器(Controller)的注解。控制器层负责接收用户请求,并根据请求处理逻辑选择合适的业务逻辑进行处理,最终返回响应给用户。

   示例代码如下:   

 1 import org.springframework.stereotype.Controller;
 2 import org.springframework.web.bind.annotation.RequestMapping;
 3 import org.springframework.web.bind.annotation.ResponseBody;
 4 
 5 @Controller
 6 @RequestMapping("/example")
 7 public class ExampleController {
 8 
 9     @RequestMapping("/hello")
10     @ResponseBody
11     public String hello() {
12    
13         return "Hello, World!";
14     }
15 }

   2. @RequestMapping

   @RequestMapping 注解是 Spring MVC 框架中的一个核心注解,用于将请求映射到相应的处理方法

   示例代码如下:  

 1 @Controller
 2 @RequestMapping("/example")
 3 public class ExampleController {
 7     @RequestMapping(value = "/hello", method = RequestMethod.GET)
 8     @ResponseBody
 9     public String hello() {
10    
11         return "Hello, World!";
12     }
13 }

  除了@RequestMapping,还可以使用@PostMapping和@GetMapping。示例代码如下:

 1 package com.controller;
 2 import org.springframework.stereotype.Controller;
 3 import org.springframework.ui.Model;
 4 import org.springframework.web.bind.annotation.GetMapping;
 5 import org.springframework.web.bind.annotation.PostMapping;
 6 @Controller
 7 public class HelloWorldController {
 8     //只接受get方式的请求
 9     @GetMapping("/testGetMapping")
10     public String testGetMapping(Model model) {
11         model.addAttribute("msg","测试@GetMapping注解");
12         return "success";
13     }
14     //只接受post方式的请求
15     @PostMapping("/testPostMapping")
16     public String testPostMapping(Model model) {
17         model.addAttribute("msg","测试@PostMapping注解");
18         return "success";
19     }
20 }

  它可以用在类级别和方法级别上,具体作用如下:

  1) 类级别的 @RequestMapping: 用于指定该类中所有处理方法的公共请求路径前缀。当用户请求的 URL 匹配该前缀时,会进入该类中的处理方法进行处理。

  2) 方法级别的 @RequestMapping: 用于指定处理请求的方法和请求路径。当用户请求的 URL 匹配该路径时,会调用该方法进行处理。

  3. @RequestParam

  @RequestParam 注解用于将 HTTP 请求中的参数绑定到控制器方法的参数上,即获取请求中的参数值并映射到方法参数。它支持几乎所有的数据类型,包括基本数据类型和复杂数据类型。

  代码示例如下:

  假设我们有一个接口 /api/foos,它接受一个名为 id 的查询参数:

1 @GetMapping("/api/foos")
2 @ResponseBody
3 public String getFoos(@RequestParam String id) {
4     return "ID: " + id;
5

  通过 GET 请求来调用 getFoos:

  http://localhost:8080/spring-mvc-basics/api/foos?id=abc
  ----
  ID: abc

  4. @PathVariable

  @PathVariable 注解用于获取 URL 中的动态参数,即将 URL 中的变量映射到控制器方法的参数上。这样就可以通过 URL 传递参数,而不是通过查询字符串的方式来传递参数。

  示例代码如下:

 1 @Controller
 2 @RequestMapping("/example")
 3 public class ExampleController {
 4    
 5   
 6     @RequestMapping(value = "/hello/{name}", method = RequestMethod.GET)
 7     @ResponseBody
 8     public String hello(@PathVariable("name") String name) {
10 
11         return "Hello, " + name + "!";
12     }
13 }

  5.  @RequestBody

  @RequestBody 注解用于将 HTTP 请求体中的数据绑定到控制器方法的参数上,即获取 POST 请求中的数据并映射到方法参数。它通常用于处理 JSON 或 XML 格式的请求体数据。

  示例代码如下:

1     @PostMapping(value = "/collaborate")
2     public BeneficiaryCollaborateResp collaborate(@RequestBody @Valid BeneficiaryCollaborateReq req) {
3          
4             //...
5     }

   6.  @ResponseBody

  @ResponseBody 注解用于将方法的返回值直接作为 HTTP 响应的内容,而不是通过视图解析器返回一个视图。它通常与 @RequestMapping 注解一起使用。

   7.  @RestController

   @RestController 是一个组合注解,它是 @Controller 和 @ResponseBody 两个注解的整合。它表示控制器类中的所有方法都会返回 JSON、XML 或其他格式的数据,而不是视图。

 1 @RestController
 2 @RequestMapping(value = "/insurance/v1/admin/event")
 3 @RequiredArgsConstructor(onConstructor_ = {@Autowired})
 4 public class AdminInsuranceEventController {
 5     private final AdminInsuranceEventService adminInsuranceEventService;
 6 
 7     @PostMapping(value = "/statistics")
 8     public AdminEventStatisticsResp eventStatistics(@RequestBody @Valid EventQueryReq req) {
 9 
10         //...
11     }
12 }

   8. @ModelAttribute
   @ModelAttribute 注解用于绑定请求参数到方法的参数或方法级别的模型属性上。

   9.  @SessionAttributes
   @SessionAttributes 注解是用于将模型属性暂时存储在会话(Session)中的注解。它可以用在控制器类级别或控制器方法级别。

   10.  @ExceptionHandler

   @ExceptionHandler 注解用于定义一个处理异常的方法。它可以用在控制器类级别或控制器方法级别。

   示例代码:

   在控制器类级别使用 @ExceptionHandler

 1 @ControllerAdvice
 2 public class GlobalExceptionHandler {
 3 
 4     @ExceptionHandler(Exception.class)
 5     public ModelAndView handleException(Exception e) {
 6      
 7         ModelAndView mv = new ModelAndView();
 8         mv.addObject("errMsg", "系统异常:" + e.getMessage());
 9         mv.setViewName("error");
10         return mv;
11     }
12 }

   六、@Enable*注解说明

   这些注解主要用来开启对xxx的支持。 

   1. @EnableAspectJAutoProxy:开启Spring对AspectJ自动代理的支持。

   示例代码如下:

1 @Configuration
2 @ComponentScan("com.yp")
3 @EnableAspectJAutoProxy
4 public class SpringConfig {
5 
6 }

   @EnableAsync: 开启异步方法的支持。
   @EnableScheduling: 开启计划任务的支持。
   @EnableWebMvc :开启Web MVC的配置支持。
   @EnableConfigurationProperties :开启对@ConfigurationProperties注解配置Bean的支持。
   @EnableJpaRepositories:开启对SpringData JPA Repository的支持。
   @EnableTransactionManagement:开启注解式事务的支持。
   @EnableTransactionManagement: 开启注解式事务的支持。
   @EnableCaching: 开启注解式的缓存支持。

   七、常用的特殊注解

   1. @PostConstruct

   1)相关介绍

   从Java 5 开始引入的注解,指的是在项目启动的时候执行这个方法,也可以理解为在spring容器启动的时候执行,可作为一些数据的常规化加载,比如数据字典之类的。

   被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。

   2)执行顺序

   通常我们会是在Spring框架中使用到@PostConstruct注解,该注解的方法在整个Bean初始化中的执行顺序:

   Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

   3)应用场景

   如果想在生成对象时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。

   举个例子:

 1 @Component
 2 public class MyUtils {
 3  
 4     private static MyUtils staticInstance = new MyUtils();
 5  
 6     @Autowired
 7     private MyMethorClassService myService;
 8  
 9     @PostConstruct
10     public void init(){
11         staticInstance.myService = myService;
12     }
13  }

 

   参考链接:

   https://developer.aliyun.com/article/1357291

   https://cloud.tencent.com/developer/article/2350497

   https://juejin.cn/post/6844904035342893063

posted @ 2024-05-21 09:50  欢乐豆123  阅读(55)  评论(0编辑  收藏  举报