自定义注解
在java1.5,提出了注解的概念,注解封装了大量的功能,让我们的编程变得更加的轻松加愉快。
在我们日常工作中,如果能合理的使用自定义注解,就能大大的减少我们的代码量,这样会大大提高我们的工作效率。那么怎样自定义注解呢,话不多说,上代码
创建注解
这一步主要设置注解的名称,添加元注解(注解的注解),我们只做一些基础的配置
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author orange
*/
// 定义注解生效范围
@Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE,ElementType.METHOD})
// 定义注解生命周期
@Retention(RetentionPolicy.RUNTIME)
public @interface Mouse {
// 设置value默认值123123
String value() default "123123";
}
@Retention:表示该注解的生命周期,是RetentionPolicy类型的,该类型是一个枚举类型,可提供三个值选择,分别是:CLASS
、RUNTIME
、SOURCE
-
RetentionPolicy.SOURCE:注解只保留在源文件中,当java文件编译成class文件时被遗弃
-
RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
-
RetentionPolicy.RUNTIME:注解不仅会保留到class文件,jvm加载class文件后,仍然会存在
由此可见:RUNTIME>CLASS>SOURCE,所以一般我们都会使用RUNTIEM
@Target:表示该注解的作用范围,是ElementType类型的,该类型是一个枚举类型,一共提供了10个值选择
- ElementType.PACKAGE:该注解只能声明在一个包名前。
- ElementType.ANNOTATION_TYPE:该注解只能声明在一个注解类型前。
- ElementType.TYPE:用于接口、类、枚举、注解
- ElementType.CONSTRUCTOR:该注解只能声明在一个类的构造方法前。
- ElementType.LOCAL_VARIABLE:该注解只能声明在一个局部变量前。
- ElementType.METHOD:该注解只能声明在一个类的方法前。
- ElementType.PARAMETER:该注解只能声明在一个方法参数前。
- ElementType.FIELD:该注解只能声明在一个类的字段前。
定义注解行为
这一步是设置注解可以干什么,这里面有五个方法,@Before(方法开始前),@Around(环绕执行),@After(方法结束后),@AfterReturning(结果返回后),@AfterThrowing(在方法抛出异常后)
@Before
: 前置通知, 在方法执行之前执行,这个通知不能阻止连接点前的执行(除非它抛出一个异常)。@After
: 后置通知, 在方法执行之后执行(不论是正常返回还是异常退出)。@Around
: 包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。@AfterRunning
:返回通知, 在方法正常返回结果之后执行 。@AfterThrowing
: 异常通知, 在方法抛出异常之后。
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.annotation.After;
import org.springframework.stereotype.Component;
/**
* @author orange
*/
@Aspect // aop注解
@Component // 代表这个是一个组件,SpringBoot启动时才会将这个类注册进容器中
public class KingMouseAspect {
// 用于打印日志
private final static Logger LOGGER = LoggerFactory.getLogger(KingMouseAspect.class);
/**
* 标记此方法在方法执行前执行,打印设置的注解的value值
*/
@Before(value = "@annotation(mouse)")
public void doBefore(Mouse mouse) {
String value = mouse.value();
LOGGER.info("@KingMouse before msg: [{}]", value);
}
/**
* 标记此方法在方法执行后执行,打印设置的注解的value值
*/
@After(value = "@annotation(mouse)")
public void testAround(Mouse mouse) {
String value = mouse.value();
LOGGER.info("@KingMouse around msg: [{}]", value);
//do something
}
}
验证测试
我们新建一个SpringBoot项目,写一个Controller,定义一个接口进行测试
@Controller
public class BasicController {
// http://127.0.0.1:8080/hello?name=lisi
@RequestMapping("/hello")
@ResponseBody
@Mouse
public String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) {
return "Hello " + name;
}
}
启动SpringBoot项目,出现端口号,则表示启动成功
打开浏览器,访问http://localhost:8080/hello进行测试
浏览器结果
控制台打印结果
至此,我们的自定义注解就算是成功了,其实,注解的本质还是aop(面向切面编程)
希望这篇文章能给你带来帮助!!!