springboot常用注解使用及原理解析
从源码上手,一通百通。
文章目录
- 前话
- 什么是注解?
- 注解如何起作用?
- springboot的常用注解
- @Controller
- @Serveice和@Component和@Repositry和@Controller
- @ReponseBody
- @RestController使用
- @ConfigurationProperties
- 总结
前话
学习springboot的注解之前,先了解注解是个什么东西,有什么用?并且注解是如何生效的?
什么是注解?
注解本质上是一个接口。
java自带的几个注解,叫元注解,元注解可以用来标识给其他注解。
0.元注解
元注解主要学习三个。
@Target
@Retention
@Documented
@Target(ElementType.TYPE)
表明该注解用在哪儿?方法上还是类上还是属性值上。
@Target括号里面的值,可以填的有:
public enum ElementType {
/** 类,接口上 */
TYPE,
/** 表明可以用于属性上 */
FIELD,
/** 方法上 */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/**构造器上 */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** 包上 */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Retention(RetentionPolicy.RUNTIME)
表明注解生效的范围,这里是运行时生效,也有源码时生效,不过通常是运行时生效。
@Documented
文档~表明可以用于什么文档啥的,没啥用。
1.自定义注解
package Annoation;
import java.lang.annotation.*;
@Documented
@Retention (RetentionPolicy.RUNTIME)//运行时生效
@Target (value = ElementType.TYPE)//可以在方法上 在字段上使用等
public @interface MyAnnoation {
String value() default "a class";//值
}
与定义接口一样,使用关键字@interface,差别是注解里面声明的是属性值,而不是方法。
上述的注解MyAnnoation可以用在类上并且运行时生效。
注解如何起作用?
注解通过反射生效,通过反射我们可以得到不管是类的所有注解,并且得到注解的值,根据这些值我们就可以进行相应的操作。
例如springboot里面中央调度器DispatcherServlet就是根据标注了注解@Controller的类找相应的处理器HandleServlet。
测试:
FiledChuan注解:
package Annoation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
* @description:
* @author java川
* @date 2019/3/5
* @param
* @throws
* @return
*/
@Retention(RetentionPolicy.RUNTIME)//运行时生效
@Target(ElementType.FIELD)//用在参数上
public @interface FieldChuan{
String columnName();//列名
}
User类:
package pojo;
import Annoation.FieldChuan;
import Annoation.MyAnnoation;
/**
* @Author 张川
* @博客 https://blog.csdn/weixin_43919632
* @Date 2019-03-5-14:37
*/
@MyAnnoation(value = "User.class")
public class User {
@FieldChuan(columnName = "db_name")
public String name;
public User(String name) {
this.name = name;
}
public User() {
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
测试方法:
import Annoation.FieldChuan;
import Annoation.MyAnnoation;
import pojo.User;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @Author 张川
* @博客 https://blog.csdn/weixin_43919632
* @Date 2021-03-05-14:37
*/
public class MainTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//反射获取User字节码Class
Class cl = Class.forName ("pojo.User");
Class cl2 = new User ().getClass ();
//反射获得类的注解
Annotation[] annotations = cl.getAnnotations ();
for (Annotation annotation : annotations) {
System.out.println ("获得注解=====》" + annotation);
}
//反射获得注解的值
MyAnnoation annotation = (MyAnnoation) cl.getAnnotation (MyAnnoation.class);
System.out.println ("annotation.value () = " + annotation.value ());
//获得属性的注解的值
Field name = cl.getDeclaredField ("name");
FieldChuan annotation1 = name.getAnnotation (FieldChuan.class);
System.out.println ("annotation1 = " + annotation1.columnName ());
}
}
springboot的常用注解
@Controller
表明这是Controller类,MVC层中的Controller层。
用户前端发起请求,中央调度器DispatcherServlet就会根据处理器映射器找到标注了@Controller注解的类,从而找到相应的处理器方法来处理请求。
@Serveice和@Component和@Repositry和@Controller
👉解析注解@Compnent工作原理
@ReponseBody
从以下源码,写的注释中知道:
这个疏解就是返回值到前端,而不会被视图解析器解析成视图。
@Target({ElementType.TYPE, ElementType.METHOD})
可以使用在类和方法上。
/**
* Annotation that indicates a method return value should be bound to the web
* response body. Supported for annotated handler methods.
*
* <p>As of version 4.0 this annotation can also be added on the type level in
* which case it is inherited and does not need to be added on the method level.
*
* @author Arjen Poutsma
* @since 3.0
* @see RequestBody
* @see RestController
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
}
@RestController使用
@RestController用在类上,标注类里面的所有方法不用被视图解析解析,而是直接返回数据。
该注解的源码:
可以看到该注解集成两个@Controller和@ReponseBody注解。表明该类就是一个接口类,不会被视图解析器解析,而是直接返回数据。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
* @since 4.0.1
*/
@AliasFor(annotation = Controller.class)
String value() default "";
}
@ConfigurationProperties
源码:
/**
* Annotation for externalized configuration. Add this to a class definition or a
* {@code @Bean} method in a {@code @Configuration} class if you want to bind and validate
* some external Properties (e.g. from a .properties file).
* <p>
* Binding is either performed by calling setters on the annotated class or, if
* {@link ConstructorBinding @ConstructorBinding} is in use, by binding to the constructor
* parameters.
* <p>
* Note that contrary to {@code @Value}, SpEL expressions are not evaluated since property
*
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigurationProperties {
String prefix() default "";
//...
}
从注释中:
这是一个额外扩展的注解,可以加到一个定义了的类(放到容器),用于在你想要绑定的额外的一些属性上,通过创建propertes文件的形式。
绑定是否生效时通过setter方法或者构造器的方式,因此我们在使用注解@ConfigurationProperties的时候,这个类要创建构造器或者setter方法,否则不能生效。
可以通过@value注解方式,使用spel表达式从properties文件中取值赋值给相应的属性。
还有重要的一点:我们要使用@EnableAutoConfiguration放在主类上,用于开启属性自动配置。
EnableXXXX什么的,都是用于开启什么服务之类的~。
总结
注解呢,其实只要了解了本质,知道看它的源码就能明白它到底是个什么东西,知道怎么使用。
java中呢,能够通过反射来获取注解上的一些东西,从而能根据注解上的东西做不同处理。
更多相关文章👉@Component解析原理
👉spingMVC请求处理过程
👉springboot自动装配原理
更多推荐
springboot常用注解@Controller等注解的使用并从原理解析
发布评论