java自定义注解并使用

一、什么是注解?

注解:源代码的元数据,代码的标签
本质一:就是一个附属品,依赖其他元素存在(比如类、方法);
本质二:本身没有任何作用,在恰当的时候由外部程序解析产生作用(通过反射);

二、编写并使用自定义注解

自定义注解:

package cn.fllday;
 
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * 自定义注解
 * @author gssznb
 *
 */
@Documented
@Inherited
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Init {
	public String value() default "hello";
}

创建数据模型并使用注解

package cn.fllday;
 
/**
 * User.java
 * 数据模型中使用注解
 * @author gssznb
 *
 */
public class User
{
    private String name;
    private String age;
 
    public String getName()
    {
        return name;
    }
 
    @Init(value = "liang")
    public void setName(String name)
    {
        this.name = name;
    }
 
    public String getAge()
    {
        return age;
    }
 
    @Init(value = "23")
    public void setAge(String age)
    {
        this.age = age;
    }
}

反射获取注解中的数据

package cn.fllday;
 
import java.lang.reflect.Method;
 
/**
 * 使用构造工厂当作 注解解析器
 * 
 * @author gssznb
 *
 */
public class UserFactory {
 
	public static User create() {
		User user = new User();
		// 获取User类中的所有方法。 (getDeclareMethods) 
		Method[] methods = User.class.getMethods();
		for (Method method : methods) {
			if (method.isAnnotationPresent(Init.class)) {
				Init init = method.getAnnotation(Init.class);
				try {
					System.out.println(init.value());
					method.invoke(user, init.value());
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return null;
				}
			}
		}
		return user;
	}
	
}

调用方法。和打印值

package cn.fllday;

public class Test {


    public static void main(String[] args) {
        User u = UserFactory.create();
        System.out.println(u.getName());
        System.out.println(u.getAge());
    }

    liang
    23
    liang
    23

}
 

注解的作用:

  • 简化配置
  • 增加代码可读性
  • 提高系统可维护性

注意:如果自定义注解只有一个成员,则成员必须取名为value(),在赋值时可忽略成员名和赋值号(=)

上面是我运行别人的代码,成功后Ctrl+C/V的,下面是本人亲自操刀,自己理解的。

1、 自定义一个注解(@MyAnnotation本身只是标记)

package com.tanhua.es.annotion;


import java.lang.annotation.*;

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

    String value() default "lisi";

    int num() default 0;
}

2、有一个Student类,想利用自己写的@MyAnnotation 注解给上面的字段赋值

package com.tanhua.es.pojo;

import com.tanhua.es.annotion.MyAnnotation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {

    @MyAnnotation("zhangsan")
    private  String name;
    private Integer age;
}

3、要想使注解生效,需要通过反射来进行

package com.tanhua.es.annotion;

import com.tanhua.es.pojo.Student;

import java.lang.reflect.Field;

public class MyAnnotationTest {

    public static Student create() {

        Student student = new Student();
        //暴力反射Student类里面的所有字段(包括私有的)
        Field[] fields = student.getClass().getDeclaredFields();
        //遍历所有字段,看哪些字段上加了@MyAnnotation注解
        for (Field field : fields) {
            field.setAccessible(true);
            MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);
            if (annotation != null) {
                try {
                //将注解里面的值赋值给student对象里的字段
                    field.set(student, annotation.value());
                    //field.set(student,annotation.num());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return student;

    }


}

4、通过我们反射后得到的Student对象,和直接new Student对象的打印结果如下:

package com.tanhua.es;

import com.tanhua.es.annotion.MyAnnotationTest;
import com.tanhua.es.pojo.Student;

public class Test {

    public static void main(String[] args) {
        //必须使用反射才能使注解生效
        Student student = MyAnnotationTest.create();
        System.out.println(student);//Student(name=zhangsan, age=null)
        //未使用反射创建的Student对象,字段没有任何赋值
        Student s=new Student();
        System.out.println(s);//Student(name=null, age=null)
    }
}

5、总结

  • 自定义注解>>>>>注解加到Student类对象上(成员变量/方法)>>>>反射得到Student对象里的成员>>>>>>>判断哪些字段上标记了注解>>>>>>>将注解里的值赋给Student的成员
  • 直接new Student()是无效的,因为没有走我们写的反射过程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值