0


Spring、SpringMVC、SpringBoot、SpringCloud 框架常用注解说明

Spring 常用注解

Configuration 配置类 相关注解

  • @Configuration:标注在类上,声明该类为 Spring 配置类Spring 在启动的时候会自动扫描并加载所有配置类,配置 Spring 容器(应用上下文),将配置类中的 Bean 放入容器管理
  • @Bean:标注在 Spring 配置类中的方法上,注册 bean 对象到 IOC 容器- name 属性:给生成的bean指定唯一标志在 Spring 容器启动的时候,自动的扫描并执行所有配置了 @Bean 的方法,并将返回值存入Spring容器注意:- 被标注的方法,需要返回某个实例- 被标注的方法,可以配置依赖的属性参数,Spring 会自动从容器中获取到依赖的对象,自动调用方法
  • @Primary:在某些情况下,需要注册多个相同类型的 bean,此时可以使用 @Primary 来赋予某个 bean 更高的优先级
  • @ComponentScan:开启包扫描(Spring IOC注解支持),默认扫描当前包及子包下所有类- basePackage 属性:指定扫描的包路径。可以减少加载时间如果扫描到类上有 IOC 注解,就会把当前类交给 IOC 容器管理,当容器启动时,自动创建对象存入容器如果扫描到属性上有 DI 注解,则依据依赖注入的规则,给属性注入值
  • @PropertySource:加载本地 properties 文件交给 Spring 容器管理- value 属性:指定本地 properties 路径
  • @Import:在一个配置类中导入其它配置类的内容- value 属性:指定其他的配置类的 class 类路径Spring 支持多配置类(配置类的模块),若配置类臃肿,可以拆分配置类,然后在主配置类中引入子配置类(子配置类上不用配置注解)
  • @Conditional@Condition 是在 Spring 4.0 增加的条件判断功能,通过这个可以功能可以实现选择性的创建 Bean 操作@Conditional 标注在配置类上或配置类的方法上,和 @Configuration 配合使用,@Conditional 指定的条件成立,配置类里面的内容才生效SpringBoot常用条件注解:- @ConditionalOnBean:容器中存在指定Bean- @ConditionalOnMissingBean :容器中不存在指定Bean- value 属性:作为条件的类的Class对象数组- type 属性:作为条件的类的 Name 数组(Class.getName())- annotation 属性:bean 上拥有指定的注解数组- name 属性:spring 容器中 bean 的名字- @ConditionalOnProperty:系统中指定的属性是否有指定的值- value / name 属性:配置名称,完整名称或部分名称(name 与 value 不可同时使用)可以与 prefix 配合使用可以传数组支持多个条件的组合(多个条件逻辑与)若想使用多个条件逻辑或:- 方式1:使用 @ConditionalOnExpression 写“逻辑或”表达式@ConditionalOnExpression("${app.dictionary:false} || ${app.all:false}")- 方式2:使用 @ConditionalOnExpression 写“默认值”嵌套表达式@ConditionalOnExpression("${app.dictionary:${app.all:false}}")- prefix 属性:配置前缀(可有可无)- havingValue 属性:对比值,与 name 组合使用,该值与配置中值相同,则配置生效,不相同则配置不生效- matchIfMissing 属性:缺少该配置属性时是否可以加载。缺少配置时, true: 正常加载,false:报错。默认为 false- @ConditionalOnClass :系统中有指定的类- @ConditionalOnMissingClass: 系统中没有指定的类- @ConditionalOnExpression :满足SpEL表达式指定- @ConditionalOnSingleCandidate :容器中只有一个指定的Bean,或者这个Bean是首选Bean- @ConditionalOnResource :类路径下是否存在指定资源文件- @ConditionalOnWebApplication :当前是web环境- @ConditionalOnNotWebApplication :当前不是web环境- @ConditionalOnJava:系统的java版本是否符合要求

IOC(容器)相关注解

  • @Controller:一般标注在表现层(web层)的类上
  • @Service: 一般标注在业务层(service层)的类上
  • @Repository: 一般标注在持久层(dao层)的类上
  • @Component:组件, 非三层模式范围的类上使用

说明

  • 标注在想要被 IOC 容器管理的类上,表明创建对象交给容器管理
  • 当 Spring 容器启动时,根据包扫描配置自动的扫描到 IOC 注解,反射创建注解标注的对象,存入容器,委托容器管理
  • 默认存入容器的 id(唯一标识)为当前类名首字母小写。可以通过 value 属性自定义存入容器中对象的 id

@Import 注解:把类导入 Spring IOC容器

有多种方式能让类加 IOC容器管理,如@Bean、@Component等,@Import 是另外一种方式,更加快捷。

支持三种方式:

  • 带有 @Configuration 的配置类(4.2版本之前只可以导入配置类,4.2版本之后 也可以导入普通类)
  • ImportSelector 的实现
  • ImportBeanDefinitionRegistrar 的实现

主要用法:

  • 直接填 class 数组方式@Configuration@Import({User.class})// 大括号中可以添加多个类,使用逗号分隔,例如 {User.class,UserInfo.class}publicclassUserConfig{}

  • ImportSelector 方式(Spring Boot 底层采用比较得多的方式)// 自定义ImportSelectorpublicclassMyImportSelectorimplementsImportSelector{@OverridepublicString[]selectImports(AnnotationMetadata importingClassMetadata){// 返回的是需要加载的类名数组 注意这里需要的是类的全路径returnnewString[]{"com.itheima.redis.entity.User"};}}``````@Configuration@Import(MyImportSelector.class)publicclassUserConfig{}

  • ImportBeanDefinitionRegistrar 方式这种方式和 ImportSelector 方式类似,不过这种方式可以自定义Bean在容器中的名称// 自定义ImportBeanDefinitionRegistrarpublicclassTestImportBeanDefinitionRegistrarimplementsImportBeanDefinitionRegistrar{@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadata annotationMetadata,BeanDefinitionRegistry registry){RootBeanDefinition rootBeanDefinition =newRootBeanDefinition(TestD.class);//自定义注册bean registry.registerBeanDefinition("testD1111",rootBeanDefinition);}}``````@Import({TestImportBeanDefinitionRegistrar.class})@ConfigurationpublicclassImportConfig{}

  • 注意:三种用法方式都可在一个@Import中使用,需要注意的是class 数组方式、ImportSelector 方式在IOC容器中bean名称是类的全限定类名,而ImportBeanDefinitionRegistrar 方式是自定义的名称

DI(依赖注入)相关注解

DI 注解都相当于直接给属性赋值,而无需借助于 set 方法或构造方法

  • @Autowired****使用方式1:标注在属性上- 直接给属性赋值(通过 @Autowired 依赖注入,不需要配置 set 方法)- 默认是通过 by Type(根据类型,即接口类型)的形式从 IOC 容器中查找对象并给属性注入值- 如果 IOC 容器中存在多个与属性同类型的对象(一个接口有多个实现类), - 默认是按照属性名(by Name)作为唯一标志从容器中查找对象并给属性注入值- 可以和 @Qualifier 注解共同使用,指定唯一标志从容器中查找对象并给属性注入值 - value:指定 IOC 容器中对象唯一标志(id)使用方式2:标注在方法上- 表示自动执行当前方法,如果方法有参数,会自动从 IOC 容器中寻找同类型的对象给参数传值- 也可以在参数上添加 @Qualifier(“IOC容器中对象id”) 注解按照名称寻找对象给参数传值使用注意事项1. 只能在被 Spring 容器托管(标注了 @Controller 等 IOC 注解)的类中使用 @Autowired 注解2. 自动注入与权限修饰符无关,即使是 private 修饰的字段也可以自动注入3. 默认情况下,使用 @Autowired 注解进行自动注入的属性一定要被装配( Spring 容器托管)如果在容器中找不到该类型的bean 进行注入,就会报错如果允许不被装配,可以将 @Autowired 的 required 属性为 false4. @Autowired 是基于类型的注入,如果当前类型属性在容器中只有一个 Bean,那么属性名不限制,但一般建议遵循类名首字母小写的规则5. 如果当前属性类型在容器中有个多个Bean,那么必须要通过属性名或者同时标注 @Qualifier 注解指定 Bean name
  • @Qualifier:当有多个同一类型的 Bean 时,可以用@Qualifier(“name”) 来指定。只能与@Autowired配合使用
  • @value:可用于简单数据类型的注入,但通常不这么使用。标注在属性上。一般用于解析 properties 配置文件或注册中心的配置文件中的内容- 根据 key 值获取对应的 value ,语法规则: @Value(“${key}”)- 使用步骤: 1. properties 配置文件交给 Spring 容器管理2. 通过 @Value,从容器中得到配置项,并注入
  • @Reource(了解)jdk 提供的依赖注入的注解,此注解在 jdk9 及以上版本已经移除- 只能标注在被 Spring 容器托管的类的属性上- 表示先按照属性名匹配 IOC 容器中对象 id 给属性注入值【by name】- 若没有成功,会继续根据当前属性的类型匹配 IOC 容器中同类型对象来注入值 【by type】- 若指定了 name 属性 @Resource(name = “对象id”),则只能按照对象 id 注入值

AOP(方法增强)相关注解

  • @EnableAspectJAutoProxy:标注在配置类上,开启 aop 注解支持
  • @Aspect:标注在自定义类上,声明切面类注意:该切面类同时需要标注 IOC注解(@Component),交给 Spring 容器管理
  • 在切面类中的通知(增强)方法上通过注解配置通知类型:- @Before:前置通知- @AfterReturning: 后置通知- @AfterThrowing:异常通知- @After:最终通知- @Around:环绕通知通知注解的属性:- value / argNames 属性:切入点表达式 或 被 @Pointcut 标注的方法名()@Around("pt()")publicObjectaround(ProceedingJoinPoint pjp)
  • @Pointcut:标注在切面类中的空的方法上,抽取公共的切入点表达式- value / argNames 属性:切入点表达式- 通知注解配置 方法名() 即可引入公共的切入点表达式@Pointcut(value="execution(* cn.test.service.impl.*.*(..))")publicvoidpt(){}

事务管理 相关注解

  • @EnableTransactionManagement:标注在配置类上,开启事务注解支持
  • @Transactional:配置事务常用属性:- rollbackFor 属性:设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚- 指定单一异常类:@Transactional(rollbackFor=Exception.class)- 指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})- readOnly 属性:是否只读事务 ( true | false(默认值) )- propagation 属性:事务传播行为 ( SUPPORTS | REQUIRED(默认值) )- transactionManager 属性:多个事务管理器托管在 Spring 容器中时,指定事务管理器的 bean 名称- isolation 属性:设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况通常使用数据库的默认隔离级别即可,基本不需要进行设置- noRollbackFor 属性:设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚标注位置说明:- 标注在类上:该类中所有方法都具有相同的事务配置- 标注在方法上:该方法具有事务配置- 同时标注在类上和方法上:就近原则(方法上的事务配置生效)

生命周期 相关注解

  • @Scope : 在类上配置对象的作用域通过 value 属性指定作用范围(singleton|prototype),默认为 singleton(单例)
  • @PostConstruct : 配置对象创建后的触发动作当对象创建完成之后,自动执行的方法
  • @PreDestroy :配置对象销毁前的触发动作(仅在 Scope = singleton 时有效)容器关闭,对象销毁之前执行的方法

单元测试 相关注解

  • @RunWith:设置单元测试的运行器,通过 value 属性指定单元测试运行环境- SpringJUnit4ClassRunner.class:Spring 测试环境- SpringRunner.class:Spring 测试环境注:- SpringRunner extends SpringJUnit4ClassRunner.class- 使用上 JUnit4.12 或更高版本以上 SpringRunner、SpringJUnit4ClassRunner 都可以使用但是推荐使用 SpringRunner,final类型,安全- JUnit4.12 以下版本就只能使用 SpringJUnit4ClassRunner
  • @ContextConfiguration:指定容器的配置信息- localtions 属性:配置文件路径- classes 属性:配置类

异步调用 相关注解

  • @EnableAsync:标注在启动类或配置类上,使 @Async 注解生效
  • @Async:标注在一个异步切入点方法上,表示该方法异步调用此方法被调用时,会从 Spring 自带的线程池中取一个线程执行这个方法,而不是用 web 线程池中的线程,这样 web 线程池中的线程就可以用来继续服务其他新的客户端请求注意:- 该方法所在类需被 Spring 容器管理- 所修饰的函数不要定义为 static 类型,否则异步调用不会生效- 返回值:若不需要返回值,直接void;需要返回值用 AsyncResult 或者 CompletableFuture- 可指定自定义执行器(线程池),例如:@Async(“otherExecutor”)(通过 @bean 自定义一个线程池 )- 若在 Spring 中单独使用 @Async 注解,必须指定执行器(即配置线程池),否则会报错:org.springframework.aop.interceptor.AsyncExecutionAspectSupport getDefaultExecutor- 而在 SpringBoot 当中由于自动配置,直接默认配置了一个 SimpleAsyncTaskExecutor 线程池- @Async 标注的方法必须是不同类间调用: A类 ==> B类.C方法()(@Async标注在B类的C方法上)如果在同一个类中调用,会变同步执行,例如:A类.B() ==> A类.@Async C方法()原因是:底层实现是代理对注解扫描实现的,B方法上没有注解,没有生成相应的代理类。(当然把@Async加到类上也能解决,但所有方法都异步了,一般不这么用!)

Spring MVC 常用注解

Controller 相关

  • @RequestMapping:用于建立请求URL和处理方法之间的映射关系,也可以通过它的属性对请求做出各种限制可标注在类、方法上,若用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。属性:- value / path 属性:指定映射的请求地址,指定的地址可以是URI Template 模式- method 属性:指定请求的 method 类型, GET、POST、PUT、DELETE等,示例:RequestMethod.post- params 属性:指定 request 中必须包含的参数,若请求没有携带指定参数,则抛出异常- headers 属性:指定 request 中必须包含某些指定的header值,才能让该方法处理请求。- consumes 属性:指定处理请求的提交内容类型(Content-Type),如application/json,text/html;- produces 属性:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
  • @RequestParam:标注在 Controller 方法参数之前,用于对请求中 url 传入的普通参数做一些限制支持三个属性:- value / name 属性:默认属性,用于绑定请求传入的参数名称。一般在请求传参和 Controller 方法入参不一致时使用- required 属性:用于指定此参数是否必传 - @RequestParam 修饰的参数默认必须传值,可以用 required = false 来指定非必传值- defaultValue 属性:指定参数默认值(当参数为非必传参数且请求没有传入该参数时,使用默认值)若不加 @RequestParam 注解:- 前端的参数名需要和后端控制器的变量名保持一致才能生效- 参数为非必传
  • @PathVariable:映射 URL 绑定的占位符带占位符的 URL是 Spring3.0 新增的功能URL中的 {xxx} 占位符参数可以通过 @PathVariable(“xxx”) 绑定到控制器处理方法的入参中@RequestMapping("/testPathVariable/{id}")publicStringtestPathVariable(@PathVariable("id")Integer id){System.out.println("testPathVariable:"+id);returnSUCCESS;}

全局数据处理(@ControllerAdvice)

  • @ControllerAdvice:定义 Controller 层全局数据处理类。作用在注解了 @RequestMapping 的控制器方法上包含注解 @Component,可以被扫描到一般和以下注解搭配使用- @ExceptionHandler(异常处理)- @ModelAttribute(数据绑定)- @InitBinder(数据预处理)- 注意:这三个注解都可以在普通的 Controller 类上使用,ControllerAdvice只是作用范围可以自定义(默认全部)支持属性:- value / basePackages 属性: 数组类型,指定一个或多个包,用来指定可以作用的基包即将对指定的包下面的 Controller 及其子包下面的 Controller 起作用若不指定,默认所有被扫描的包- basePackageClasses 属性: 是 basePackages 的一种变形, 数组类型,指定一个或多个 Controller 类,这些类所属的包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理- assignableTypes 属性:数组类型,用来指定具体的 Controller 类型,它可以是一个共同的接口或父类等- annotations 属性: 指定一个或多个注解,被这些注解所标记的 Controller 会被该 @ControllerAdvice 管理
  • @RestControllerAdvice:定义 Controller 层全局数据处理类组合注解,由注解 @ControllerAdvice、@ResponseBody 组成
  • @ExceptionHandler:用于捕获 Controller 中抛出的不同类型的异常常与 @ControllerAdvice 注解搭配使用,从而实现全局异常处理
  • @ModelAttribute:被其标注的方法会在执行目标 Controller 方法之前执行常与 @ControllerAdvice 注解配合使用,可以让全局的 @RequestMapping 方法都能获得在此处设置的键值对
  • @InitBinder:用来设置 WebDataBinder,进行请求数据预处理

Spring Boot 常用注解

  • @SpringBootApplication:组合注解,通常标注在启动类上- @Configuration:声明该类为 Spring 配置类,把该类中定义的 Bean 加载到 Spring 容器中- @EnableAutoConfiguration:自动加载所有符合条件的 @Configuration 配置到当前 SpringBoot 环境例如:若添加了 spring-boot-starter-web 依赖,由于其使用了 Tomcat 和 Spring MVC,所以 auto-configuration 将假定正在开发一个 web应用,并对 Spring 进行相应地设置。- @ComponentScan:开启包扫描(IOC注解支持),默认扫描当前包及子包下所有类可以通过 basePackage 属性指定扫描的包路径,以减少加载时间
  • @SpringBootTest:配置文件属性的读取。在运行 SpringBoot 为基础的测试类上标注- 当定义没有特定的 @ContextConfiguration(loader=…) 时,使用 SpringBootContextLoader 作为默认的 ContextLoader- 当不使用嵌套 @Configuration 时,自动搜索@SpringBootConfiguration,并且没有指定显式的类- 允许使用 properties 属性定义自定义环境属性- 为不同的webEnvironment模式提供支持,包括启动一个完全运行的 web 服务器,监听一个已定义的或随机的端口。- 注册一个 TestRestTemplate 或 WebTestClient bean,用于在web测试中使用完全运行的web服务器
  • @ConfigurationProperties:用于自动配置绑定支持属性:- value / prefix 属性:配置文件配置项的前缀- ignoreInvalidFields 属性:默认为 false,值类型不匹配将会爆出异常- ignoreUnknownFields 属性:默认为 true,忽略掉对象中未知的字段用法1:标注在类上,转换配置文件配置项为 bean 对象- 注意: - 需要将标注了 @ConfigurationProperties 注解的类注册到spring容器中,方式有两种: - 方式1:在标注了@ConfigurationProperties 注解的类上使用 @componet 等 IOC 注解- 方式2:在标注了@componet 等 IOC 注解的类上或配置类上标注 @EnableConfigurationProperties(bean类名.class)- 需要有无参构造方法、getter和setter方法@Data@AllArgsConstructor@NoArgsConstructor@Component@ConfigurationProperties(prefix ="app.mycar")publicclassCar{privateint price;privateString brand;}``````@Configuration@EnableConfigurationProperties(Car.class)publicclassConfig{}用法2:标注在配置类的方法上,搭配 @bean 使用,绑定第三方属性@ConfigurationpublicclassDbConfig{@Bean@ConfigurationProperties(prefix ="spring.datasource.druid")publicDataSourcedatasource(){returnnewDruidDataSource();}}
  • @EnableConfigurationProperties:使 @ConfigurationProperties 注解生效,并自动将这个类注入到 IOC 容器中标注在有 @componet 等 IOC 注解的类上或配置类上支持属性:- value 属性:Class<?>[] 数组,即标注了 @ConfigurationProperties 注解的类的Class数组

Spring Cloud 常用注解

服务注册 / 服务发现 / 配置中心

  • @EnableEurekaClient:开启使用服务注册和服务发现基于spring-cloud-netflix,若选用的注册中心是 eureka,推荐使用该注解
  • @EnableDiscoveryClient:开启使用服务注册和服务发现基于spring-cloud-commons,若是其他的注册中心,推荐使用该注解
  • @EnableEurekaServer:在启动类或配置类标注,标识该服务为eureka服务端
  • @EnableConfigServer:在启动类或配置类标注,标识该服务为服务中心服务端
  • @RefreshScope:标注在类上,自动刷新从配置中心获取的数据只有添加此注解,配置中心数据刷新时,该类的对象会自动重新加载,自动更新数据注入 @value

Feign 组件

  • @EnableFeignClients:开启Feign注解。标注在启动类或配置类上项目启动时,就会启动一个 FeignSterter 组件,这个组件会对项目中使用 @FeignClient 的类创建代理对象
  • @FeignClient:声明这是一个 Feign客户端,同时通过 name / value 属性指定服务名称- 只能标注在远程服务调用的接口上(FeignClient注解被 @Target(ElementType.TYPE) 修饰,表示 FeignClient 注解的作用目标在接口上)- 当 SpringCloud 扫描到被 @FeignClient 标识的接口时,底层会为其创建实现类代理对象(jdk代理),并交给 spring容器管理(注册IOC容器);创建出来Bean对象的名字由注解的name或value属性指定,若对同一个服务创建两个远端服务调用接口时会报错- 接口中定义的方法,完全采用 SpringMVC 的注解,Feign 会根据注解生成 URL,并访问获取结果- 服务的启动类或配置类需要标注 @EnableFeignClients 注解才能使 Fegin 生效**@FeignClient注解的常用属性如下:**- name / value 属性:指定FeignClient的名称,如果项目使用了Ribbon(注册中心),name属性会作为微服务的名称,用于服务发现- url 属性:一般用于调试,可以手动指定@FeignClient调用的地址。默认为空- url可以从配置文件获取,如果有则通过url调用,没有则根据服务名调用。格式为 url = "${xxx.xxx.xxx: }"- configuration 属性:Feign配置类,可以自定义 Feign 的 Encoder、Decoder、LogLevel、Contract,可以为每一个feign client 指定不同的配置- fallback 属性:定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口- fallbackFactory 属性:工厂类,用于生成fallback类示例,通过这个属性可以实现每个接口通用的容错逻辑,减少重复的代码- path 属性:定义当前FeignClient的统一前缀,当项目中配置了server.context-path, server.servlet-path时使用- decode404 属性:当发生http 404错误时,如果该字段位 true,会调用 decoder 进行解码,否则抛出 FeignException

其他注解

  • @LoadBalanced:开启 Ribbon 负载均衡功能对 RestTemplate 添加一个LoadBalancerClient,通过 Ribbon 以实现客户端负载均衡- 标注在 RestTemplate 对象上,由 SpringCloud 的 commons 模块提供原理:当使用 RestTemplate 对象调用服务时,系统底层会对服务进行拦截,拦截到 url 后,会基于 url 的服务名获取具体的服务实例,然后基于服务实例重构 url,再基于新的 url 进行服务调用
  • @EnableCircuitBreaker:开启断路器功能
  • @EnableHystrixDashboard:在启动类或配置类标注,标识该服务为Hystrix-Dashboard服务(仪表盘),监控服务器的流量
  • @EnableTurbine:在启动类或配置类标注,标识该服务为Turbine服务,同时监控多个服务器流量
  • @EnableZuulProxy:在主启动类或配置类使用此注解,标识该服务为Zuul网关服务

lombok 常用注解

  • @Data:注解在类上;提供 getter、setter 、equals、canEqual、hashCode、toString 方法
  • @Setter:注解在属性上;为属性提供 setter 方法
  • @Getter:注解在属性上;为属性提供 getter 方法
  • @NoArgsConstructor:注解在类上;为类提供一个无参的构造方法
  • @AllArgsConstructor:注解在类上;为类提供一个全参的构造方法
  • @EqualsAndHashCode:实现 equals() 方法和 hashCode() 方法
  • @ToString:实现 toString() 方法
  • @Slf4j:注解在类上;为类提供一个 属性名为 log 的 log4j 日志对象slf4j 是一个适配器,当应用更换了一个日志源后,不需要更改代码
  • @Log4j:注解在类上;为类提供一个 属性名为 log 的日志对象log4j是真正实现日志功能的产品
  • @Cleanup:关闭流
  • @Synchronized:对象同步
  • @SneakyThrows:抛出异常

本文转载自: https://blog.csdn.net/footless_bird/article/details/128704278
版权归原作者 墨鸦_Cormorant 所有, 如有侵权,请联系我们删除。

“Spring、SpringMVC、SpringBoot、SpringCloud 框架常用注解说明”的评论:

还没有评论