Spring自从更新了2.5版本之后也开始慢慢舍弃xml配置,更多使用Spring注解来控制Spring框架,下面详解9种最常用的Spring注解。
什么是注解
Annontation是Java5开始引入的新特征,中文名称叫注解,它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。
用一个词就可以描述注解,那就是元数据,即一种描述数据的数据。所以,可以说注解就是源代码的元数据。
举一个简单的例子:
@Override public String toString() { return "my name is mikechen" ; }
上面的代码中,我重写了toString()方法并使用了@Override注解,@Override告诉编译器这个方法是一个重写方法(描述方法的元数据),如果父类中不存在该方法,编译器便会报错,提示该方法没有重写父类中的方法。
什么是Spring注解
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:
1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低
2、在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率
为了解决这两个问题,Spring引入了注解,通过”@XXX”的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。
Spring注解使用
1. 核心注解
@Required
此注解用于bean
的setter
方法上。表示此属性是必须的,必须在配置阶段注入,否则会抛出BeanInitializationExcepion
。
@Autowired
此注解用于bean
的field
、setter
方法以及构造方法上,显式地声明依赖。根据type来autowiring
。
当在field
上使用此注解,并且使用属性来传递值时,Spring会自动把值赋给此field
。也可以将此注解用于私有属性(不推荐),如下。
@Component
public class User {
@Autowired
private Address address;
}
最经常的用法是将此注解用于settter
上,这样可以在setter
方法中添加自定义代码。如下:
@Component
public class User {
private Address address;
@AutoWired
public setAddress(Address address) {
// custom code
this.address=address;
}
}
当在构造方法上使用此注解的时候,需要注意的一点就是一个类中只允许有一个构造方法使用此注解。此外,在Spring4.3后,如果一个类仅仅只有一个构造方法,那么即使不使用此注解,那么Spring也会自动注入相关的bean
。如下:
@Component
public class User {
private Address address;
public User(Address address) {
this.address=address;
}
}
<bean id="user" class="xx.User"/>
@Qualifier
当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。
@Configuration
此注解用在class上来定义bean
。其作用和xml配置文件相同,表示此bean
是一个Spring配置。此外,此类可以使用@Bean
注解来初始化定义bean
。
@Configuartion
public class SpringCoreConfig {
@Bean
public AdminUser adminUser() {
AdminUser adminUser = new AdminUser();
return adminUser;
}
}
@ComponentScan
此注解一般和@Configuration
注解一起使用,指定Spring扫描注解的package。如果没有指定包,那么默认会扫描此配置类所在的package。
@Lazy
此注解使用在Spring的组件类上。默认的,Spring中Bean的依赖一开始就被创建和配置。如果想要延迟初始化一个bean,那么可以在此类上使用Lazy注解,表示此bean只有在第一次被使用的时候才会被创建和初始化。此注解也可以使用在被@Configuration
注解的类上,表示其中所有被@Bean
注解的方法都会延迟初始化。
@Value
此注解使用在字段、构造器参数和方法参数上。@Value
可以指定属性取值的表达式,支持通过#{}使用SpringEL来取值,也支持使用${}来将属性来源中(Properties文件、本地环境变量、系统属性等)的值注入到bean的属性中。此注解值的注入发生在AutowiredAnnotationBeanPostProcessor
类中。
2. Stereotype注解
@Component
此注解使用在class上来声明一个Spring组件(Bean), 将其加入到应用上下文中。
@Controller
此注解使用在class上声明此类是一个Spring controller
,是@Component
注解的一种具体形式。
@Service
此注解使用在class上,声明此类是一个服务类,执行业务逻辑、计算、调用内部api等。是@Component
注解的一种具体形式。
@Repository
此类使用在class上声明此类用于访问数据库,一般作为DAO的角色。
此注解有自动翻译的特性,例如:当此种component
抛出了一个异常,那么会有一个handler
来处理此异常,无需使用try-catch
块。
3. Spring Boot注解
1、@SpringBootApplication
包含@Configuration、@EnableAutoConfiguration、@ComponentScan
通常用在主类上。
2、@Repository
用于标注数据访问组件,即DAO组件。
3、@Service
用于标注业务层组件。
4、@RestController
用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody
5、@ResponseBody
表示该方法的返回结果直接写入HTTP response body中
一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析
为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。
6、@Component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
7、@ComponentScan
组件扫描。相当于<context:component-scan>,如果扫描到有@Component @Controller @Service等这些注解的类,则把
这些类注册为bean。
8、@Configuration
指出该类是 Bean 配置的信息源,相当于XML中的<beans></beans>,一般加在主类上。
9、@Bean
相当于XML中的<bean></bean>,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。
10、@EnableAutoConfiguration
让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,一般加在主类上。
11、@AutoWired
byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
当加上(required=false)时,就算找不到bean也不报错。
12、@Qualifier
当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用
13、@Resource(name=”name”,type=”type”)
没有括号内内容的话,默认byName。与@Autowired干类似的事。
14、@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
该注解有六个属性:
params:指定request中必须包含某些参数值是,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
value:指定请求的实际地址,指定的地址可以是URI Template 模式
method:指定请求的method类型, GET、POST、PUT、DELETE等
consumes:指定处理请求的提交内容类型(Content-Type),如application/json,text/html;
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
15、@RequestParam
用在方法的参数前面。
1 |
|
16、@PathVariable
路径变量。参数与大括号里的名字一样要相同。
1 2 3 4 |
|
17、@Profiles
Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。
任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。
1 2 3 |
|
18、@ConfigurationProperties
Spring Boot将尝试校验外部的配置,默认使用JSR-303(如果在classpath路径中)。
你可以轻松的为你的@ConfigurationProperties类添加JSR-303 javax.validation约束注解:
1 2 3 4 5 6 |
|
全局异常处理
@ControllerAdvice
包含@Component。可以被扫描到。
统一处理异常
@ExceptionHandler(Exception.class):
用在方法上面表示遇到这个异常就执行以下方法。
4. Spring MVC和REST注解
@Controller
在展现层使用,控制器的声明。
@RequestMapping
此注解可以用在class
和method
上,用来映射web请求到某一个handler类或者handler方法上。当此注解用在Class
上时,就创造了一个基础url,其所有的方法上的@RequestMapping
都是在此url之上的。
可以使用其method属性来限制请求匹配的http method。
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping(method = RequestMethod.GET)
public String getUserList() {
return "users";
}
}
此外,Spring4.3之后引入了一系列@RequestMapping
的变种。如下:
-
@GetMapping -
@PostMapping -
@PutMapping -
@PatchMapping -
@DeleteMapping
分别对应了相应method
的RequestMapping
配置。
@CookieValue
此注解用在@RequestMapping
声明的方法的参数上,可以把HTTP cookie
中相应名称的cookie
绑定上去。
@ReuestMapping("/cookieValue")
public void getCookieValue(@CookieValue("JSESSIONID") String cookie){
}
cookie
即http
请求中name为JSESSIONID
的cookie
值。
@CrossOrigin
此注解用在class
和method
上用来支持跨域请求,是Spring 4.2后引入的。
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/users")
public class AccountController {
@CrossOrigin(origins = "http://xx.com")
@RequestMapping("/login")
public Result userLogin() {
// ...
}
}
@ExceptionHandler
此注解使用在方法级别,声明对Exception
的处理逻辑。可以指定目标Exception
。
@InitBinder
此注解使用在方法上,声明对WebDataBinder
的初始化(绑定请求参数到JavaBean
上的DataBinder
)。在controller
上使用此注解可以自定义请求参数的绑定。
@MatrixVariable
此注解使用在请求handler
方法的参数上,Spring可以注入matrix url中相关的值。这里的矩阵变量可以出现在url中的任何地方,变量之间用;分隔。如下:
// GET /pets/42;q=11;r=22
@RequestMapping(value = "/pets/{petId}")
public void findPet(@PathVariable String petId, @MatrixVariable int q) {
// petId == 42
// q == 11
}
需要注意的是默认Spring mvc是不支持矩阵变量的,需要开启。
<mvc:annotation-driven enable-matrix-variables="true" />
注解配置则需要如下开启:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
@PathVariable
@RequestMapping("/users/{uid}")
可以使用@PathVariable
将路径中的参数绑定到请求方法参数上。
@RequestMapping("/users/{uid}") public String execute(@PathVariable("uid") String uid){ }
5. 任务执行、调度注解
@Scheduled
此注解使用在方法上,声明此方法被定时调度。使用了此注解的方法返回类型需要是Void
,并且不能接受任何参数。
@Scheduled(fixedDelay=1000)
public void schedule() {
}
@Scheduled(fixedRate=1000)
public void schedulg() {
}
第二个与第一个不同之处在于其不会等待上一次的任务执行结束。
@Async
此注解使用在方法上,声明此方法会在一个单独的线程中执行。不同于Scheduled
注解,此注解可以接受参数。
使用此注解的方法的返回类型可以是Void也可是返回值。但是返回值的类型必须是一个Future
。
6. 数据访问注解
@Transactional
此注解使用在接口定义、接口中的方法、类定义或者类中的public
方法上。需要注意的是此注解并不激活事务行为,它仅仅是一个元数据,会被一些运行时基础设施来消费。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》