Java中常用注解

一、JAVA注解总结

1.说明

注解可以增强Java代码,利用反射技术可以扩充实现很多功能,被广泛应用于三大框架底层。
传统我们通过xml文本文件声明方式(但是XML比较繁琐且不易检查),而现在最主流的开发都是基于注解方式,代码量少,框架可以根据注解去自动生成很多代码,从而减少代码量,程序更易读。例如最火爆的SpringBoot就完全基于注解技术实现。

2.注解分类

  • JDK自带注解
  • 元注解
  • 自定义注解

2.1JDK注解

@Override :用来标识重写方法
@Deprecated标记就表明这个方法已经过时了,但我就要用,别提示我过期
@SuppressWarnings(“deprecation”) 忽略警告
@SafeVarargs jdk1.7出现,堆污染,不常用
@FunctionallInterface jdk1.8出现,配合函数式编程拉姆达表达式,不常用

2.2元注解

@Target 注解用在哪里:类上、方法上、属性上等等
@Retention 注解的生命周期:源文件中、字节码文件中、运行中
@Inherited 允许子注解继承
@Documented 生成javadoc时会包含注解,不常用
@Repeatable注解为可重复类型注解,可以在同一个地方多次使用,不常用

2.2.1@Target(ElementType…)

ElementType.TYPE 应用于类的元素 ElementType.METHOD 应用于方法级 ElementType.FIELD
应用于字段或属性(成员变量) ElementType.ANNOTATION_TYPE 应用于注解类型
ElementType.CONSTRUCTOR 应用于构造函数 ElementType.LOCAL_VARIABLE 应用于局部变量
ElementType.PACKAGE 应用于包声明 ElementType.PARAMETER 应用于方法的参数

2.2.2 @Retention(RetentionPolicy…)

该注解定义了自定义注解被保留的时间长短,比如某些注解仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中; 编译在class文件中的注解可能会被虚拟机忽略,而另一些在class被装载时将被读取。
在这里插入图片描述

SOURCE 在源文件中有效(即源文件保留) CLASS 在class文件中有效(即class保留) RUNTIME
在运行时有效(即运行时保留)

3.自定义注解

package cn.tedu.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/*本类用于完成自定义注解*/
public class TestAnnotation {
}
//2.通过@Target注解标记自定义注解的使用位置
/*3.通过元注解@Target规定自定义注解可以使用的位置
* 我们使用"ElementType.静态常量"的方式来指定自定义注解具体可以加在什么位置
* 而且,值可以写多个,格式:@Target({ElementType.XXX,ElementType.XXX}*/
@Target({ElementType.METHOD,ElementType.TYPE})//可以加在方法&类上
//3.通过@Retention注解标记自定义注解的生命周期
/*4.通过元注解@Retention规则自定义注解的生命周期
* 我们使用"RetentionPolicy.静态常量"的方式来指定自定义注解的生命周期
* 注意:值只能写一个:SOURCE CLASS RUNTIME 3选1 */
@Retention(RetentionPolicy.RUNTIME)//到运行时都有效
//1.定义自定义注解
/*1.首先注意:注解定义的语法与Java不同
* 2.定义自定义注解的格式:@interface 注解名*/
@interface Rice{
    //5.我们可以给注解进行功能增强--添加注解的属性
    /*5.注意:int age();不是方法的定义,而是给自定义注解添加了一个age属性*/
    //int age();//给自定义注解添加一个普通属性age,类型是int
    int age() default 0;//给自定义注解的普通属性赋予默认值0
    /*6.注解中还可以添加特殊属性value
    * 特殊属性的定义方式与普通属性一样,主要是使用方式不同
    * 注意:特殊属性的名字必须叫value,但是类型不做限制
    * 特殊属性也可以赋予默认值,格式与普通属性一样,不能简写
    * */
    //String value();//定义一个特殊属性value,类型是String
    String value() default "Lemon";//定义特殊属性并给特殊属性赋予默认值
}

//4.定义一个类用来测试自定义注解
//@Rice
class TestAnno{
    /*测试1:分别给TestAnno类 name属性 eat方法都添加Rice注解
    * 结论:属性上的注解报错了,说明自定义注解可以加在什么位置,由@Target决定*/
    //@Rice//报错了
    String name;
    /*测试2:当我们给Rice注解添加了一个age属性以后,@Rice注解使用时直接报错
    * 结论:当注解没有定义属性时,可以直接使用
    *      当注解定义了属性以后,必须给属性赋值,格式:@Rice(age = 10)*/
    /*测试3:给age属性赋予默认值以后,可以直接使用@Rice注解
    * 不需要给age属性赋值,因为age属性已经有默认值0了*/
    /*测试4:给Rice注解添加了特殊属性value以后,必须给属性赋值
    * 只不过特殊属性赋值时可以简写成 @Rice("Apple")
    * 测试5:如果特殊属性也赋予了默认值,那么可以直接使用这个注解
    * 如果要给注解的所有属性赋值,每条赋值都不能简写*/
    @Rice(age=10,value="orange")
    //@Rice("Apple")
    //@Rice(age = 10)
    //@Rice(10)//报错,不可以简写,普通属性没有这种格式
    public void eat(){
        System.out.println("干饭不积极,思想有问题");
    }
}

4.单元测试@Test

@Test 单元测试方法:是Java中最小的测试单位,使用灵活

二、Spring常用注解

1.配置类@Configuration

1.1用在方法上@Bean

@Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名。
将自己的返回值交给Spring容器管理。
案例:

@Configuration //将当前类标识为配置类
public class SpringConfig {//xml
    /**1.xml形式
     *      <bean id="user" class="com.jt.demo.User"></bean>
     * 2.注解形式
     *      Map集合的机构 Map<方法名,方法的返回值>
     */
    //@Bean("user1")
    @Bean
    public User user(){
        return new User();//反射机制
    }
}

这个配置就等于在xml里的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
        知识点讲解:该配置文件作用是管理对象
            术语: bean  被spring容器管理的对象称之为bean
            属性说明:
                  id:是spring容器中对象的唯一标识符,不能重复
                  class:对象的全路径
    -->
    <bean id="user" class="com.jt.demo.User"></bean>
</beans>

2.将当前类交给Spring容器管理@Component

@Component 将当前的类,交给Spring容器管理, 对象的创建是由Spring通过反射机制自动创建对象。

3.指定路径包扫描@ComponentScan(“com.jt”)

@ComponentScan(“com.jt”) 指定扫描的包路径, 可以扫描它的子孙包,用在配置类中

4.控制对象单例/多例@Scope

可在配置类中@Bean中添加此注解
@Scope(“singleton”) 默认就是单例模式
@Scope(“prototype”) 设置为多例模式

5.懒加载@Lazy

  • 如果Spring容器创建,对象立即创建则该加载方式为“立即加载”,容器启动就创建;
  • 如果Spring容器创建,对象在被使用的时候才创建,则称为“懒加载”,对象用时才创建。
    @Lazy表示为懒加载
    测试说明:主要测试对象中的无参构造什么时候执行!!
    只要对象是多例模式,则都是懒加载
    在单例模式中加此注解懒加载才有效

6.Spring生命周期注解

6.1.在对象创建之后立即调用@PostConstruct

init()此方法加上@PostConstruct生效

6.2.对象消亡时调用@PreDestroy

destroy()此方法对象消亡时调用
案例:

package com.jt.demo;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component  //将对象交给Spring容器管理 key=person value:反射对象
public class Person {

    public Person(){
        System.out.println("张三出生了,资质拉满");
    }

    @PostConstruct  //在对象创建之后立即调用
    public void init(){
        System.out.println("张三称为少年奇才");
    }

    //业务方法
    public void doWork(){
        System.out.println("迎娶美人鱼!!!");
    }

    @PreDestroy //对象消亡时 进行调用
    public void destory(){
        System.out.println("销毁:全世界哀悼");
    }
}

7.在对象中需要属性注入@Autowired注解

将Spring容器中的对象注入到属性中,如果需要依赖注入,则对象必须交给Spring容器管理
注入方式:
1.默认是按照类型注入,如果注入的属性是接口,则自动注入实现类的属性
2.按照名称注入(key),一般不用

7.1接口只有一个实现类

编辑Pet接口:

public interface Pet {
    void hello();
}

编辑Pet接口实现类:

package com.jt.demo;

import org.springframework.stereotype.Component;

@Component //将对象交给spring容器管理 key:cat value:反射Cat对象
public class Cat implements Pet{

    @Override
    public void hello() {
        System.out.println("我是喵喵喵");
    }
}

编辑User类:

package com.jt.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component  //将user交给Spring容器管理
public class User {

    //效果: 将当前接口的实现类自动注入
    @Autowired
    private Pet pet;

    public void say(){
        //调用宠物的方法
        pet.hello();
    }
}

7.2接口有多个实现类@Autowired + @Qualifiter(“小写类名”)

package com.jt.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component  //将user交给Spring容器管理
public class User {

    //效果: 将当前接口的实现类自动注入
    @Autowired
    @Qualifier("cat") //该注解不能单独使用,必须配合Autowired使用,根据key进行注入
    private Pet pet;  //2选1

    public void say(){
        //调用宠物的方法
        pet.hello();
    }
}

7.3与@Autowired + @Qualifier(“小写类名”)效果相同@Resource(name = “小写类名”)

8.Spring框架注解

8.1控制层@Controller

控制层 Controller 与前端页面交互的. @Controller

8.2业务层@Service

业务层 Service 编辑业务逻辑. @Service

8.3持久层,暂时用@Repositiry

持久层 Mapper 实现数据库的相关操作 暂时:@Repository

9.动态赋值@Value

@Value注解 可以直接为基本类型赋值和String类型
编辑UserMapperImpl类

@PropertySource(value = “classpath:/user.properties”,encoding = “utf-8”)

user.properties文件路径及编码方式

package com.jt.mapper;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Repository;

@Repository  //为了让程序员开发更有层级概念
@PropertySource(value = "classpath:/user.properties",encoding = "utf-8")  //  :/ 代表资源加载路径
public class UserMapperImpl implements UserMapper{

    //耦合性,动态赋值
    //表达式: 固定写法${}  springel表达式 取值方式 缩写spel表达式
    //规则:通过表达式动态获取spring容器中的value
    @Value("${id1}")
    private int id1;
    @Value("${name1}")
    private String name1;

    @Override
    public void addUser() {
        System.out.println("新增用户id:"+id1+"新增用户姓名:"+name1);
    }
}

编辑user.properties

#1.key=value 等号连接 2.之间不要添加多余的空格
id1=008
name1=张三

10.AOP(面向切面编程)中的注解

10.1开启AOP,在配置中加入@EnableAspectJAutoProxy

10.2标识切面类@Aspect

10.3@Pointcut注解标识切入点表达式

10.3.1切入点表达式
  • @Pointcut(“bean(userServiceImpl)”) (bean的id号)按照bean匹配
  • @Pointcut(“within(com.jt.service.UserServiceImpl)”) (包名.类名)可以使用通配符
    @Pointcut(“within(com.jt.service…*)”)
  • @Pointcut(“execution(* com.jt.service.UserServiceImpl.addUser())”) (返回值类型 包名.类名.方法名(参数列表))
    @Pointcut(“execution(* com.jt.service….(…))”)
  • @Pointcut("@annotation(com.jt.anno.Gjh)") (包名.注解名称) 按照自定义注解
 @Pointcut("@annotation(com.jt.anno.Gjh)")
 //目标方法
public void pointcut(){

}

@annotation表达式
作用: 可以根据用户的自定义注解进行拦截

10.3.2通知类型注解
  1. @Before(“pointcut()”) 前置通知:在目标方法执行之前执行
  2. @AfterReturning(value = “pointcut()”,returning =
    “result”) 后置通知:在目标方法执行之后执行,通过returning =
    "result"属性,获取目标方法的返回值,当作参数传给result
  3. @AfterThrowing(value = “pointcut()”,throwing =
    “exception”) 异常通知:目标方法执行报错时,执行该通知
  4. @After(“pointcut()”) 最终通知:目标方法之后都要执行的通知
  5. @Around(“pointcut()”) (重点)环绕通知:在目标方法执行前后都要执行,控制目标方法
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint)throws Throwable{
    System.out.println("环绕通知执行前");
    Object result = joinPoint.proceed();
    System.out.println("环绕通知执行后");
    return result;
}

10.4执行AOP顺序@Order(数字)

数字越小越靠前

11.SpringMVC注解

11.1@ResponseBody将数据转化为JSON串返回

11.2@RequestBody将接收到的JSON串转为对象

@PostMapping("/saveUser")
public String saveUser(@RequestBody User user){
    System.out.println(user);
    return "新增用户成功!!!";
}

11.3@RestController

@RestController将该类交给SpringMVC,SpringMVC将该类交给Spring容器管理将数据转化为JSON串返回
和@Controller + @ResponseBody效果相同

11.4@RequestMapping("/方法名")

此注解在前后端交互时,浏览器地址栏输入注解中 /方法名

11.5restFul风格 @PathVariable

  /**
     * URL地址:
     *  http://localhost:8080/findUser/tomcat/18/男  get类型
     * 参数: name/age/sex
     * 返回值: 返回值获取的数据
     * restFul语法:
     *     1. 参数与参数之间使用/分割
     *     2. 需要接收的参数使用{}包裹
     *     3. 参数接收时采用@PathVariable取值
     */
    @RequestMapping("/findUser/{name}/{age}/{sex}")
    public String findUser(@PathVariable String name,
                           @PathVariable int age,
                           @PathVariable String sex){

        return name+":"+age+":"+sex;
    }

11.6允许所有方式跨域@CrossOrigin

11.7接收固定请求方式注解

11.7.1@PostMapping("/saveUser")
11.7.2@GetMapping
11.7.3@PutMapping
11.7.4@DeleteMapping

restful参数传给方法的参数时,每个参数都需加@PathVariable注解(不管是什么访问方式);restful参数传给对象时,不需要加注解。
POST和PUT访问方式访问时,方法的参数为对象,需要加@RequestBody注解(Json串转为对象)

11.8@RequestParam在controller层使用

  1. 为参数设定默认值
  2. 当提交参数名称与接收参数不一致时使用
    例:
 /**
     * 如果提交参数为空时,可以设置默认值
     * 	@RequestParam
     * 		value/name 接收参数的名称
     * 		required=true 为必填参数
     * 		defaultValue="" 设定默认值
     */
    @RequestMapping("/addUser")
    public String addUser(@RequestParam(name = "id",defaultValue = "100") Integer id,
                          @RequestParam(name="name",defaultValue = "张三") String name){

        System.out.println("动态获取数据:id:"+id);
        System.out.println("动态获取数据:name:"+name);
        //新增成功之后.跳转到user页面中
        return "user";
    }

11.9@Param在mapper层使用

  1. 为参数设定默认值
  2. 当提交参数名称与接收参数不一致时使用

12.lombok使用

12.1@Data

@Data相当于Getter/Setter/RequiredArgsConstructor/ToString/EqualsAndHashCode

12.2@Accessors(chain = true)重写了set方法,可实现链式加载

12.3@NoArgsConstructor无参构造方法

12.4@AllArgsConstructor全参构造方法

13. @SpringBootApplication启动类标识

13.1@ComponentScan(“包路径”)

当前包扫描的路径 默认就是主启动类所在的包路径…
注意事项: 以后写代码 必须在主启动类所在包路径的 同包及子包中编辑

13.2@EnableAutoConfiguration开箱即用-自动配置注解

该注解的作用用来加载springBoot-start-xxx的启动项,当主启动类执行时,则会开始加载启动项中的配置.则功能加载成功.

14.@SpringBootTest

springBoot针对于测试方法

  1. 当运行@Test注解标识的方式时,SpringBoot程序启动.
  2. SpringBoot启动,内部Spring容器启动.基于IOC管理对象,DI注入对象
  3. 可以在任意的测试类中注入想要的对象
    测试类的包路径,必须在主启动类的同包及子包中编辑

15.@Mapper将接口交给Spring容器管理

@Mapper 将接口交给Spring容器管理Map<userMapper,JDK代理对象>

16.@Param将数据封装为Map集合

mybatis只支持单值传参 将多值封装为单值
@Param(“key”) int minAge(值)

//Mybatis只支持单值传参    封装为Map集合
List<User> findUserList(@Param("start") int start,@Param("size") int size,@Param("query") String query);

17.@Transactional 事务的注解

一级缓存注解
增删改加上@Transactional 注解
特点:
1.Spring中默认对事务进行支持。
2.Spring中默认控制的是运行时异常,如果是检查异常Spring不负责处理。
核心原理:AOP
常见案例:
@Transactional(rollbackFor = Exception.class) 只要有异常,则全部回滚
问题:如果采用上述的代码,则AOP拦截所有的异常,运行效率低,所以一般只拦截运行时异常,检查异常由程序员手动控制。

18.@CacheNamespace 使用注解的二级缓存

19.Mybatis注解开发@Select,@Insert,@Update,@Delete

20.MapperSan(“路径”) 扫描mapper包的接口

21.全局异常处理的机制实现

21.1 @RestControllerAdvice

全局异常处理机制,只拦截Controller层

21.2 @ExceptionHandler

@ExceptionHandler(RuntimeException.class)指定异常的类型进行拦截

package com.jt.aop;

import com.jt.vo.SysResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice   //advice通知
//全局异常处理机制,只拦截Controller层
public class SystemException {

    //指定异常的类型进行拦截
    @ExceptionHandler(RuntimeException.class)
    public SysResult exception(Exception e){
        e.printStackTrace(); //控制台打印异常信息
        return SysResult.fail();//201
    }
}

22.MybatisPlus常用注解

22.1@TableName(“user”)让对象与表名一一映射

22.2 @TableId(type = IdType.AUTO)标识主键注解,主键自增

编辑POJO对象
在这里插入图片描述

22.3@TableField(exist = false)当前属性不参加MP操作

pojo对象

@Data
@Accessors(chain = true)
@TableName("item_cat")
public class ItemCat extends BasePojo{
    @TableId(type = IdType.AUTO)//主键自增
    private Integer id;         //定义主键
    private Integer parentId;   //定义父级菜单
    private String name;        //分类名称
    private Boolean status;     //分类状态 0 停用 1 正常
    private Integer level;      //商品分类等级  1 2 3
    @TableField(exist = false)   //当前属性不参加MP操作
    private List<ItemCat> children; //业务数据
}

22.4@TableField(fill = FieldFill.INSERT)、@TableField(fill = FieldFill.INSERT_UPDATE) 自动填充

在这里插入图片描述

三、微服务中注解

23.@LoadBalanced

当使用@LoadBalanced注解描述RestTemplate对象时,系统底层再基于RestTemplate进行远程服务调用时,会被一个拦截器(Interceptor)拦截到,然后进行功能增强,这里功能增强指的是:基于LoadBalancerClient对象进行服务实例获取,而这个服务实例获取的过程,底层会采用负载均衡。

24.@EnableFeignClients

@EnableFeignClients 注解用于描述一些配置类,告诉系统启动时为@FeignClient 注解描述接口创建实现类及对象,然后把对象交给spring管理。

25.@FeignClient描述远程服务调用接口

@FeignClient 注解用于描述远程服务调用接口,其value属性值有两个层面的含义:第一个是需要的远程服务名,第二个是当前bean的名字
@FeignClient描述的接口底层会为其创建实现类

26.@RefreshScope系统在浏览器中能看到日志级别的变化

第一步:在ProviderLogController类的上面添加一个@RefreshScope注解:
@RefreshScope的作用是在配置中心的相关配置发生变化以后,能够及时看到类中属性值的更新(底层是通过重新创建Controller对象的方式,对属性进行了重新初始化)。

@RefreshScope
@RestController
public class ProviderLogController{
  //.....
}

第二步:添加ProviderLogController中添加一个获取日志级别(debug<info<warn<error)的的属性和方法:

@Value("${logging.level.com.jt:error}")
private String logLevel;
@GetMapping("/provider/log/doLog02")
public String doLog02(){
   log.info("log level is  {}",logLevel);
   return  "log level  is "+logLevel;
}

27.@SentinelResource

Sentinel流控规则分析:
链路模式只记录指定链路入口的流量。也就是当多个服务对指定资源调用时,假如流量超出了指定阈值,则进行限流。被调用的方法用@SentinelResource进行注解,然后分别用不同业务方法对此业务进行调用,假如A业务设置了链路模式的限流,在B业务中是不受影响的。

28.缓存

28.1@EnableCaching开启spring中的缓存机制,扫描哪个类中用到了缓存

在这里插入图片描述

28.2@Cacheable(value = “permissionCache”)

此注解描述的方法为缓存切入点方法,从数据库查询到数据后, 可以将数据存储到本地的一个缓存对象中(底层是一个map对象)

28.3CachePut注解的意思是更新缓存

key是方法中参数,这里需要id,通过对象获取id

@CachePut(value = "menuCache",key = "#menu.id")
@Override
public Menu updateMenu(Menu menu) {
    menuMapper.updateById(menu);
    return menu;
}

29@EnableAuthorizationServer在Oauth2规范中启动认证和授权

在主启动类上使用

30.@Async 注解描述方法为一个异步切入点方法

此方法会有一个spring内置的线程池中的线程调用执行,
注意:描述的方法不能有返回值;
需要通过@EnableAsync注解对项目的启动类或者配置类进行描述,启动异步机制。

31.@EnableEurekaServer 触发eureka server的自动配置

32.@EnableZuulProxy注解启用zuul网关,加在启动类上

33.@EnableTurbine加在启动类上,从多台服务器抓取日志,进行聚合

34.@RabbitListener(queues = “队列名”) 通过注解来接收rabbitmq消息,加在类上,也可直接加在接收rabbitmq消息的方法上

34.1@RabbitHandler //指定处理消息的方法,在同一个类中,只能设置一次

  • 4
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值