首先什么是注解?
以前,XML是各大框架的青睐者,它以松耦合的方式完成了框架中几乎所有的配置,但是随着项目越来越庞大,XML的内容也越来越复杂,维护成本变得越来越高。
于是就有人提出来一种标记式高耦合的配置方式,注解。方法上可以进行注解,类上也可以注解,字段属性上也可以注解,反正几乎需要配置的地方都可以进行注解。
关于注解和XML两种不同的配置模式,争论了好多年了,各有各的优劣,注解可以提供更大的便捷性,易于维护修改,但耦合度高,而 XML 相对于注解则是相反的。
追求低耦合就要抛弃高效率,追求效率必然会遇到耦合。本文意不再辨析两者谁优谁劣,而在于以最简单的语言介绍注解相关的基本内容。
不使用注解和使用注解对比:
注解快速入门
@Controller
简单说Controller就是负责解析用户的输入,处理后返回相应的结果。
标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象。
1.在 RESTful 接口中,Controller 接受用户的参数,从数据库中查找内容返回给用户或者将用户的请求更新到数据库中。
2.在 HTML 页面请求中,Controller 根据用户访问不同的 URL,渲染不同的模板得到 HTML 返回给用户。
3.在代理服务器中,Controller 将用户的请求转发到其他服务器上,并将其他服务器的处理结果返回给用户。
框架推荐 Controller 层主要对用户的请求参数进行处理(校验、转换),然后调用对应的 service 方法处理业务,得到业务结果后封装并返回:
1.获取用户通过 HTTP 传递过来的请求参数。
2.校验、组装参数。
3.调用 Service 进行业务处理,必要时处理转换 Service 的返回结果,让它适应用户的需求。
4.通过 HTTP 将结果响应给用户。
@Controller
public class TestController {
@RequestMapping("/test")
public String test(Map<String,Object> map){
return "hello";
}
}
@RestController
@RestController注解,相当于@Controller+@ResponseBody两个注解的结合。
返回json数据不需要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp、html页面,视图解析器无法解析jsp,html页面
Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。
@RestController=@Controller+@ResponseBody两个注解,
注解为止在controller类上,相当于整个类中所有方法的返回值都为json字符串
@RestController
public class TestController {
@RequestMapping("/test")
public String test(Map<String,Object> map){
return "hello";
}
}
@service
用于标注业务层组件,以注解的方式把这个类注入到spring配置中。
service 是有用的相当于 xml配置中得bean id = service
也可以不指定 不指定相当于 bean id = com. service.service
就是这个类的全限定名,表示给当前类命名一个别名,方便注入到其他需要用到的类中;不加的话,默认别名就是当前类名,但是首字母小写 。
注解用于类上,标记当前类是一个service类,加上该注解会将当前类自动注入到spring容器中,不需要再在applicationContext.xml文件定义bean了。
简单理解就是:告诉spring,我这个service接口的实现类是这个,你帮我在spring容器里创建它。
**@Service(“userService”)**注解是告诉Spring,当Spring要创建UserServiceImpl的的实例时,bean的名字必须叫做"userService",这样当Action需要使用UserServiceImpl
的的实例时,就可以由Spring创建好的"userService",然后注入给Action:在Action只需要声明一个名字叫“userService”的变量来接收由Spring注入的"userService"即可
如果不懂bean的同学可以参考Java Bean详解
JavaBean可以看成是一个黑盒子,即只需要知道其功能而不必管其内部结构的软件设备。
黑盒子只介绍和定义其外部特征和与其他部分的接口,如按钮、窗口、颜色、形状、句柄等。
@Service
public class TestService {
public String test(Map<String,Object> map){
return "hello";
}
}
@Autowired
用来装配bean,都可以写在字段上,或者方法上。
spring中可以借助**@Autowired**注解描述属性,用于告诉spring这个属性的值由spring注入
@Autowired这个注解就是spring可以自动帮你把bean里面引用的对象的setter/getter
方法省略,它会自动帮你set/get
默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,例如:@Autowired(required=false)
它还可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。
在使用**@Autowired**之前,我们对一个bean配置起属性时,是这用用的
<property name="属性名" value=" 属性值"/>
通过这种方式来,配置比较繁琐,而且代码比较多。在Spring 2.5 引入了 @Autowired 注释
@RestController
public class TestController {
@Autowired(required=false)
private TestService service;
@RequestMapping("/test")
public String test(Map<String,Object> map){
return "hello";
}
}
@RequestMapping
类定义: 提供初步的请求映射信息,相对于 WEB 应用的根目录。
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
RequestMapping注解有六个属性,下面我们把她分成三类进行说明。
1、 value, method;
value:指定请求的实际地址,指定的地址可以是URI Template 模式;
method:指定请求的method类型, GET、POST、PUT、DELETE等;
2、 consumes,produces;
consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
3、 params,headers;
params: 指定request中必须包含某些参数值是,才让该方法处理。
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
@RestController
public class TestController {
@RequestMapping("/test")
public String test(Map<String,Object> map){
return "hello";
}
}
@Bean
产生一个bean的方法,并且交给Spring容器管理,相当于配置文件中的 <bean id="" class=""/>
复制代码
@Bean
public class UserTest(){
public User getUser(){
System.out.println("创建user实例");
return new User("张三",26);
}
}
@Component
spring框架中定义的用于描述一般bean对象的一个注解springBoot工程在启动时会自动扫描启动类所在的包及其子包中的类,并读取这些类的描述,加入这些类使用了类似@Component这样的注解描述,它会交给spring管理
把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>
它泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。
此外,被@controller 、@service、@repository 、@component 注解的类,都会把这些类纳入进spring容器中进行管理
复制代码
什么是pojo?POJO详细讲解
POJO实质上可以理解为简单的实体类,顾名思义POJO类的作用是方便程序员使用数据库中的数据表,对于广大的程序员,可以很方便的将POJO类当做对象来进行使用,当然也是可以方便的调用其get,set方法。POJO类也给我们在struts框架中的配置带来了很大的方便。
@Component
public class TestClass {
public String test(Map<String,Object> map){
return "hello";
}
}
@MapperScan
1、@Mapper注解:
作用:在接口类上添加了@Mapper,在编译之后会生成相应的接口实现类
添加位置:接口类上面
@Mapper
public interface UserDAO {
//代码
}
如果想要每个接口都要变成实现类,那么需要在每个接口类上加上@Mapper注解,比较麻烦,解决这个问题用@MapperScan
2、@MapperScan
程序会自动为mybatis创建代理对象,这只要把存放所有接口的文件夹路径给他就可以不在接口类上写@Mapper了
作用:指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类
添加位置:是在Springboot启动类上面添加,
@SpringBootApplication
@MapperScan("com.winter.dao")
public class SpringbootMybatisDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootMybatisDemoApplication.class, args);
}
}
添加@MapperScan(“com.winter.dao”)注解以后,com.winter.dao包下面的接口类,在编译之后都会生成相应的实现类
3、使用@MapperScan注解多个包
(实际用的时候根据自己的包路径进行修改)
@SpringBootApplication
@MapperScan({"com.kfit.demo","com.kfit.user"})
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
@SpringBootApplication
来标识这是一个主程序类,说明这是一个springboot应用
@SpringBootApplication 注解描述的类为speringboot工程启动类,这个启动类会通
@SpringBootApplication注解告诉springboot工程
1)基于线程调用i/O从磁盘读取类,将其加载到内存,此时会基于类创建字节码对象(其类型为Class对象)
2)基于Class对象(字节码对象)读取类的配置信息(例如类上有什么注解,属性上有什么注解等)
3)基于类的配置进行相应的配置存储(交给spring管理的类的配置)—BeanDefinition-Map<String, BeanDefinition>
4)基于类的配置结组BeanFactory创建类的实例(对象),多个对象存储到Map<String, Object>
@SpringBootTest
SpringBoot工程中的单元类需要使用@SpringBootTest注解进行描述
@Lazy
延迟加载:
延迟对象实例的创建,用的时候再去创建
@Scope
单例/多例作用域:
1)@Scope(“singleton”)注解
默认单例作用域,此作用域通常会配合延迟加载使用
2)@Scope(“prototype”) 注解
多例作用域,每次从spring请求类的实例都会创建新的对象,使用完后就销毁了,不会调用销毁方法
@PostConstruct
1)@PostConstruct生命周期初始化注解
@PostConstruct,生命周期初始化方法,构造方法之后执行,可以在此方法内部做一些初始化
例如:
@PostConstruct
public void 方法名(){
System.out.println("初始化");
}
2)@PreDestroy生命周期销毁注解
@PreDestroy,生命周期销毁方法,对象销毁之前执行,可以在对象销毁前做一些资源释放操作
例如:
public void 方法名(){
System.out.println("销毁");
}
@Qualifier
用于区分多个实现类,在项目中由多个实现类时用,通过这个标示,表明了哪个实现类才是我们所需要的 @Qualifier("实现类名")
例如:
- @Qualifier(“softCache”)
@Repository
此注解一般描述数据逻辑层的具体实现对象,此对象要交给spring管理
@Mapper
描述数据逻辑层接口,告诉Mybatis框架这个接口的实现类,由Mybatis创建,并将其实现类的对象交给spring管理,spring会为他管理的这个bean起个名字,默认为接口名,然后首字母小写。
@DateTimeFormat()
此注解可以自定义日期格式类型,注解写在形参处
例如:@DateTimeFormat(pattern = "yyyy-MM-dd")
默认:@DateTimeFormat(pattern = "yyyy/MM/dd")
@Controller
此注解描述的对象为Controller请求的处理器对象,我们通常称之为handler
@ResponseBody
当使用此注解描述控制层的handler方法时,假如此方法的返回值为map或pojo这样的对象,系统底层会将这样的转换为json格式字符串,然后响应给客户端
@RequestParam
这个注解用于描述方法参数,用于定义参数规则
1)方法参数变量的值,来自哪求参数,例如:@RequestParam("username") //指定网页变量名
2)方法参数变量是否必须传值,例如:@RequestParam(required = true)
3)可以指定方法中的形参必须有客户端的返回值,否则网页报错,例如:@RequestParam
@RequestBody
描述方法参数时,客户端可以以post方式提交json格式的数据
@PathVariable
用于修饰形参(配合@GetMapping注解使用),描述方式参数变量时,表示这个参数的值来自url中{}表达式给的定值
例如:
@GetMapping("/doParam10/{id}")
public String doMethodRestUrlParam(@PathVariable Integer id){
return "request params id's value is"+id;
}
@value("${}")
这个注解就是把容器内的数据获取到类里,${容器内数据的构造},注解修饰变量就可以将容器内的值交给变量存储
例如:容器内数据为
redis:
host: 192.168.1.1
${}内就写
${redis.host}就可以获取到数据
@PropertySource
@PropertySource(value = "classpath:路径",encoding = "utf-8")
此注解用来指定程序启动加载指定的配置文件
value = "classpath:路径"
这是.properties文件的根路径,例如:value = "classpath:user.properties"
encoding = "utf-8"
这是.properties文件读取时的编码格式
@Accessors(chain = true)
此注解为链式加载
例如:
User user = new User();
user.setName("A").setAge(11).setSex(0);
@TableName注解
需要MybatisPlus插件,用来修饰POJO类
这个注解就是定义表名与POJO对象名之间的关系
例如:对象名是User,就表示查询的表名为user
也可以指定表名,例如@TableName("user")
@TableId(type = IdType.AUTO)注解
需要@TableName
修饰类后,此注解修饰变量,设置变量主键自增
Lombok插件注解
@Data
此注解是Lombok插件注解
此注解描述类的时候,可以自动为函数添加get/set/toString方法
@slf4j
此注解是Lombok插件注解
发现类上有此注解是,会为此类创建一个日志对象,其对象名为long
如果不想每次都写private final Logger logger = LoggerFactory.getLogger
(当前类名.class); 可以用注解
@AllArgsConstructor
此注解是Lombok插件注解
此注解描述的类为有参构造函数
@NoArgsConstructor
此注解是Lombok插件注解
此注解描述的类为无参构造函数
@Setter/@Getter/@toString/
此注解为Lombok插件注解
可以为类单独设置某种类型
Controller请求系列代码
@RequestMapping("/")
@RequestMapping
注解描述方法是用于定义请求url到handler中方法的映射
@return view
的名字
个人理解:这就是到时访问网页时的名称,比如括号内些/ABC
,到时访问网址就是http://localhost/ABC
这样,注意,括号内一定要写斜杠,名称最好和方法名相同
在不是代码类型时使用!
@GetMapping("/")
查询应该使用GET
修饰方法为REST风格,URL的定义/path/{var1}/{var2}
例如:@GetMapping("/doParam10/{id}")
@PostMapping("/")
增加应该使用POST
可以用来修饰方法为post网页,在客户端访问时可以为括号内的简单名
例如:@PostMapping("/doParam09")
Post向服务器发数据。依照HTTP协议,Post的语义是向服务器添加数据,也就是说按照Post的语义,该操作是会修改服务器上的数据的。
Post请求是不可以被缓存的。对于Post方式提交表单,刷新页面浏览器会弹出提示框 “是否重新提交表单”,Post可以接收二进制等各种数据形式,所以如果要上传文件一般用Post请求。
POST和GET都是向服务器提交数据,并且都会从服务器获取数据。
区别:
1、传送方式:get通过地址栏传输,post通过报文传输。
2、传送长度:get参数有长度限制(受限于url长度),而post无限制
3、GET和POST还有一个重大区别,简单的说:
GET产生一个TCP数据包;POST产生两个TCP数据包
@DeleteMapping
使用CRUD 删除时,我们应该使用@DeleteMapping标注,
@PutMapping
使用CRUD 修改时,修改应该使用@PutMapping标注
AOP系列注解
@Aspectz
注意:需要引入aop的配置文件
注解描述的类为切面对象类型,此切面中可以定义多个切入点和通知方式
@Pointcut
注意:需要配合@Aspectz注解
注解用于定义切入点
@Pointcut("bean(bean名称)"):bean(bean名称)
,这个表达式为切入点表达式定义的一种语法,它描述的是某个bean或多个bean中方法的集合为切入点,多个bean写法为@Pointcut("bean(*bean名称)")
@Around()
注解描述的方法,可以在切入点执行之前和之后执行,在当前业务中,此方法为日志通知方法
所有通知中优先级最高的通知,可以在目标方法执行之前,之后灵活进行业务扩展
@Retention()
可以用来修饰注解,是注解的注解,称为元注解
RetentionPolicy.SOURCE:注解只保留在源文件,在java文件被编译为class文件时被遗弃
RetentionPolicy.CLASS:注解被保留在class文件,当jvm加载class文件时被遗弃这是默认的生命周期
RetentionPolicy.RUNTIME:注解被保留在class文件,当jvm加载class文件时任然存在
取值 | 有效范围 |
---|---|
SOURCE | 在源文件中有效(即源文件保留) |
CLASS | 在class文件中有效(即class保留) |
RUNTIMR | 在运行时有效(即运行时保留) |
@Target
表示注解的作用范围,一旦超过这个范围,编译就会报错
target通过ElementType来指定作用范围
取值 | 注解使用范围 |
---|---|
TYPE | 可用于类或者接口上 |
FIELD | 可用于域上 |
METHOD | 可用于方法上 |
PARAMETER | 可用于参数上 |
CONSTRUCTOR | 可用于构造方法上 |
LOCAL_VARIABLE | 可用于局部变量上 |
ANNOTATION_TYPE | 可用于注解类型上(被interface修饰的类型) |
PACKAGE | 用于记录java文件的package信息 |
@pointcut()
切入点表达式
针对于Advice通知方法的执行时间的一些注解:
- @Around 前后都可以执行,注意:有严格顺序要求时使用此注解
- @Before 目标方法执行之前执行此方法进行功能增强
- @AfterReturning 目标方法没有出现异常顺利结束时执行它
- @AfterThrowing 执行目标方法出现异常时执行它
- @After 不论目标方法是否执行成功我都要执行它进行功能增强,这个方法一般用作资源的释放;
@Before()
AOP的使用方法,表示在目标方法执行之前调用
@AfterReturning()
AOP的使用方法,表示目标方法执行正常结束时调用
@AfterThrowing()
AOP的使用方法,表示目标方法异常结束时执行
@After()
AOP的使用方法,表示目标方法结束时执行
@Documented
Document的英文意思是文档。
它的作用是能够将注解中的元素包含到 Javadoc 中去。