大纲
你接触的注解有哪些?常用的有哪些?能记住的有哪些?知道他们具体是干什么的吗?本章为你解惑。
本文采取分类的方式进行注解讲解,方便记忆,对于比较容易混淆的注解,给与了实例讲解,希望对你会有帮助。
一、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
,只不过@Autowired
按byType
自动注入,而@Resource
默认按byName
自动注入罢了。@Resource有两个属性是比较重要的,分是name
和type
,Spring
将@Resource
注解的name
属性解析为bean
的名字,而type
属性则解析为code>bean的类型。所以如果使用name
属性,则使用byName
的自动注入策略,而使用type
属性时则使用byType
自动注入策略。如果既不指定name
也不指定type
属性,这时将通过反射机制使用byName
自动注入策略。
@Resource装配顺序
1. 如果同时指定了name
和type
,则从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();
}
}
这个测试用例,我们使用@Autowired
对Animal animal;
进行依赖注入,我么知道@Autowired
是根据类型进行注入的,这时候的类型就是Animal
,但是依赖注入是,是根据具体实现进行注入的,而且具体实现只能有一个时,他才能知道注入哪一个实现类,因此,此处这样写一定会报错,我们执行一下看看吧。
报错的地方给我们提示了:but found 2: Cat,Dog
,思是Animal
有两个实现类。解决方案如下:
- 还是使用
@Autowired
注解,但是我们需要为其设置具体的实现类型,这是就需要一个新的注解:@Qualifier
,如下图修改代码:
- 使用
@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
路径会继承注解在类上的路径。同时支持Serlvet
的request
和response
作为参数,也支持对request
和response
的媒体类型进行配置。其中有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
类并把它加入到程序上下文。
4.2 @EnableAutoConfiguration:自动配置
此注释自动载入应用程序所需的所有Bean
——这依赖于Spring Boot
在类路径中的查找。该注解组合了@Import
注解,@Import
注解导入了EnableAutoCofigurationImportSelector
类,它使用SpringFactoriesLoader.loaderFactoryNames
方法来扫描具有META-INF/spring.factories
文件的jar
包。而spring.factories
里声明了有哪些自动配置.
4.3 @Configuration:配置文件
等同于spring
的XML
配置文件;使用Java
代码可以检查类型安全。
4.4 @ComponentScan:自动扫描
表示将该类自动发现扫描组件。个人理解相当于,如果扫描到有@Component、@Controller、@Service
等这些注解的类,并注册为Bean
,可以自动收集所有的Spring
组件,包括@Configuration
类。
五、AOP常用的注解
5.1 @Aspect:切面
声明一个切面
5.2 @After:后置建言
后置建言(advice),在原方法前执行
5.3 @Before:前置建言
前置建言(advice),在原方法后执行。
5.3 @Around:环绕
环绕建言(advice),在原方法执行前执行,在原方法执行后再执行(@Around可以实现其他两种advice)。
5.3 @PointCut:切点
声明切点,即定义拦截规则,确定有哪些方法会被切入
六、测试常用的注解
6.1 @SpringBootTest
@SpringBootTest注解是SpringBoot Since:1.4.0 版本开始引入的一个用于测试的注解。
6.2 @Test
将一个普通方法修饰为一个测试方法。
6.3 @RunWith
这个是Junit的注解,springboot集成了junit。一般在测试类里使用:@RunWith(SpringJUnit4ClassRunner.class)
— SpringJUnit4ClassRunner在JUnit环境下提供Sprng TestContext Framework的功能
最主要是声明测试的运行器,都在org.junit.runners下。
@RunWith(SpringRunner.class) ,表明这个类中的测试用例需要使用SpringRunner类来执行。
6.4 其他测试注解
1. @Ignore : 被忽略的测试方法
2. @Before: 每一个测试方法之前运行
3. @After : 每一个测试方法之后运行
4. @BeforeClass: 所有测试开始之前运行
5. @AfterClass: 所有测试结束之后运行
七、其他注解:都是比较常用的
7.1 @Transactional:事务声明
声明事务(一般默认配置即可满足要求,当然也可以自定义)
7.2 @Cacheable:缓存
声明数据缓存
7.3 @PropertySource:文件引入
指定文件地址。提供了一种方便的、声明性的机制,用于向Spring的环境添加PropertySource。与@configuration类一起使用。
7.4 @Async:多线程异步方法
注解在方法上标示这是一个异步方法,在类上标示这个类所有的方法都是异步方法。
7.5 @EnableAsync:多线程
开启异步任务支持。注解在配置类上。
7.6 @EnableScheduling:开启计划任务
注解在配置类上,开启对计划任务的支持。
7.7 @Scheduled:计划任务
注解在方法上,声明该方法是计划任务。支持多种类型的计划任务:cron,fixDelay,fixRate。