Java中注解讲解及实战

注解在java中是个很常见很重要的元素, 它的出现简化了我们的业务,由之前的一大段代码逻辑过渡到了一个注解就解决问题,当然注解也只是偏向于解释型的注释而已,需要生效还需要其他功能,最多的也就是反射了。本文将讲述注解如何定义,以及如何用。

说到注解,那就要说说四大元注解啦。

四大元注解

1.@Target

@Target({ElementType.TYPE})

该注解用于注明该注解用在什么地方。几个重要值如下

参数值意义
ElemenetType.CONSTRUCTOR用于构造器上
ElemenetType.FIELD用于属性上
ElemenetType.METHOD用于方法上
ElemenetType.TYPE类,接口(包括注解类型)或enum声明

2. @Retention

表示在什么级别保存该注解。有如下值可选

参数值意义
RetentionPolicy.SOURCE用于源码上。编译时将丢弃
RetentionPolicy.CLASSclass文件有效。运行时将丢弃
RetentionPolicy.RUNTIME运行时有效

3.@Documented

该注解用于javadoc中为我们自动生成文档

4.@Inherited

该注解表示该允许子类继承父类中的注解

了解了这四个元注解,我们来看怎么用。

1.首先创建一个注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * AnnotationTest class
 *
 * @author greatwhite
 * @date 20200723
 */
@Target({ElementType.TYPE,ElementType.CONSTRUCTOR,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest {
    String id();
    String name() default "测试注解";
    String desc();
}

 

实验中我只用上了@Target、@Retention两个注解,其他两个用得不多。

给了该注解在类上、构造方法上、方法上、属性上的声明,并且是运行时有效,这点很关键,不然后面的反射是获取不到该注解的。

2.将注解用于People类上:

**
 * @ClassName People
 * @Author greatwhite
 * @Date 2020/7/23 0023 13:44
 * @Version
 **/
@AnnotationTest(id="0",name="类注解",desc="类注解")
public class People {
    @AnnotationTest(id = "1",name = "属性注解",desc = "属性注解")
    private String name;

    @AnnotationTest(id = "2",name = "构造方法注解",desc = "构造方法注解")
    public People(String name) {
        this.name = name;
    }
    @AnnotationTest(id = "3",name = "方法注解",desc = "方法注解")
    public void test(){
        System.out.println("方法注解");
    }
}

 

给People的类上、构造方法上、方法上、属性上都加了该注解。那么注解用上了,怎么拿到呢?

3.获取注解值

我们通过反正拿到注解信息,下面是测试类:

//获取构造方法上的注解
@Test
    public void testConstructorAnnotation() throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.wt.annotation.People");
        Constructor<?>[] constructors = aClass.getConstructors();
        for(Constructor c:constructors){
            Annotation[] annotations = c.getAnnotations();
            for(Annotation a:annotations){
                if(a.annotationType() == AnnotationTest.class){
                    AnnotationTest test = (AnnotationTest) a;
                    System.out.println("id:" + test.id() + "|name:" + test.name() + "|desc:" + test.desc());
                }
            }
        }

    }
//获取类上注解
@Test
    public void testTypeAnnotation() throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.wt.annotation.People");
        Annotation[] annotations = aClass.getAnnotations();
        for(Annotation a:annotations){
            if(a.annotationType() == AnnotationTest.class){
                AnnotationTest test = (AnnotationTest) a;
                System.out.println("id:" + test.id() + "|name:" + test.name() + "|desc:" + test.desc());
            }
        }
    }

//获取方法上的注解
@Test
    public void testMethodAnnotation() throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.wt.annotation.People");
        Method[] methods = aClass.getMethods();
        for(Method m:methods){
            Annotation[] annotations = m.getAnnotations();
            for(Annotation a:annotations){
                if(a.annotationType() == AnnotationTest.class){
                    AnnotationTest test = (AnnotationTest) a;
                    System.out.println("id:" + test.id() + "|name:" + test.name() + "|desc:" + test.desc());
                }
            }
        }
    }

//获取属性上的注解
@Test
    public void testFieldAnnotation() throws ClassNotFoundException, NoSuchFieldException {
        Class<?> aClass = Class.forName("com.wt.annotation.People");
        //由于name是私有成员变量,注意使用getDeclaredField方法
        Field name = aClass.getDeclaredField("name");
        Annotation[] annotations = name.getAnnotations();
            for(Annotation a:annotations){
                if(a.annotationType() == AnnotationTest.class){
                    AnnotationTest test = (AnnotationTest) a;
                    System.out.println("id:" + test.id() + "|name:" + test.name() + "|desc:" + test.desc());
                }
        }
    }
结果:
id:2|name:构造方法注解|desc:构造方法注解
id:0|name:类注解|desc:类注解
id:3|name:方法注解|desc:方法注解
id:1|name:属性注解|desc:属性注解

这样就获取到了注解行的值啦,是不是很方便啦,一般在实际springBoot开发项目中,注解通常与AOP结合使用,通过AOP获取注解的参数值,场景最多的就是日志记录了。

接下来就让我们一起来加入项目实战吧。

以SpringBoot项目为例:

首先定义注解:

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysServiceLog {

    String operateContent() default "";

    String description() default "";

    int operateType() default 7;
}

定义切面:

@Aspect
@Component
public class ServiceAspect {


    private static final Logger logger = LoggerFactory.getLogger(ServiceAspect.class);

    private final static Log log = LogFactory.getLog(ServiceAspect.class);

    // 配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
    @Pointcut("@annotation(com.cec.common.annotation.SysServiceLog)")
    public void aspect() {
    }

    /*
     * 配置前置通知,使用在方法aspect()上注册的切入点 同时接受JoinPoint切入点对象,可以没有该参数
     */
    @Before("aspect()")
    public void before(JoinPoint joinPoint) {
       //日志记录
    }

    // 配置后置通知,使用在方法aspect()上注册的切入点
    @After("aspect()")
    public void after(JoinPoint joinPoint) {
        //日志记录
    }
 // 配置后置返回通知,使用在方法aspect()上注册的切入点
    @AfterReturning(pointcut = "aspect()", returning = "object")
    public void afterReturn(JoinPoint joinPoint, Object object) {
        //日志记录
}
}

然后我们只需要在控制层将注解写在接口上即可。

@RestController
@RequestMapping("testLog")
@SysServiceLog(operateContent = "保存预约规则", operateType = Globals.Log_Type_INSERT)
public String testLog(){
return "日志测试";
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值