注解及自定义注解

    xiaoxiao2024-11-05  119

    目录

    初识注解自定义注解查看某类上是否标有某注解isAnnotationPresent使用自定义注解解析自定义注解利用注解自己实现一个简单的spring框架,实现IOC和DI

    初识注解

    import java.lang.annotation.*; /** *所有的注解默认继承自Annotation注解(本质是一个继承Annotaion的接口) * 4个元注解(修饰注解的注解,且只能修饰注解,元注解的target=ElementType.ANNOTATION_TYPE): * @Target @Retention @Inherited @Documented * @Target:允许标注的位置 * ElementType.TYPE:类上 * ElementType.FIELD:属性上 * ElementType.METHOD:方法上 * @Retention:注解的保留策略(只有保留到运行时的注解才可以通过反射获取) * RetentionPolicy.SOURCE:仅存在于源文件里(不可以通过反射读取) * RetentionPolicy.CLASS:存在到class字节码文件里(不可以通过反射读取) * RetentionPolicy.RUNTIME:保留到运行时候(可以通过反射读取) * * 源代码文件---编译---》字节码文件--加载----》JVM * * SOURCE CLASS RUNTIME * @Inherited:注解是否可以被继承,父类标有的注解如果可继承,那么他的子类自动继承注解(接口和接 * 口实现类不支持继承注解,只支持父类和子类) * @Documented:此注解是否能被文档所记录 */ @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface MyAnnotation { /** * 自定义注解用:@interface标识 * >>属性都是默认 public static final修饰(myValue) * >>方法都是默认 public abstract修饰 * >>方法设有默认值的,使用注解不用必须指定值,没有设置默认值必须指定 * >>方法必须有返回值,但是没有参数,使用的时候直接把参数传给方法名字即可 * >>返回值必须是以下6种类型 * 1.基本数据类型 * 2.String类型 * 3.Class类型 * 4.注解类型 * 5.枚举类型 * 6.一维数组类型,但是数组内部的元素都必须是以上5种类型 **/ String myValue = "test"; int getNum();//1.基本数据类型 String name() default "";//2.String类型(有默认值) Class<? extends UserFather> getClazz();//3.Class类型 Override getAnnotation();//4.注解类型 MyColorEnum getColorEnum();//5.枚举类型 String[] strArr();//6.一维数组类型,但是数组内部的元素都必须是以上5种类型 }

     

    查看某类上是否标有某注解isAnnotationPresent

    public class My {     public static void main(String[] args) {         Class<My1> my1Class = My1.class;         boolean annotationPresent = my1Class.isAnnotationPresent(Documented.class);         System.out.println("annotationPresent = " + annotationPresent);     } }

    自定义注解

    @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface MyAnnotation { String name() default ""; String value(); }

     

     

    使用自定义注解

    public class User extends UserFather { @MyAnnotation("张三")//不指定方法名:则默认是给value()方法指定的 private String userName; private String password; private Integer age; @MyAnnotation(value = "张三", name = "三") public void test() { } //get set ....... } public class My {     public static void main(String[] args) {         Class<My1> my1Class = My1.class;         boolean annotationPresent = my1Class.isAnnotationPresent(Documented.class);         System.out.println("annotationPresent = " + annotationPresent);     } }

     

    解析自定义注解

    @Test public void test() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { /** * 解析注解值的前提是反射: * 获取类上的注解:需要首先获取 Class--->clazz.getDeclaredAnnotation(MyAnnotation.class) * 获取field上的注解:需要想先获取到field -->userNameField.getDeclaredAnnotation(MyAnnotation.class) * 获取method上的注解:需要想先获取到method--->testMethod.getAnnotation(MyAnnotation.class) * 获取到注解后直接--》注解实例.方法名就可以获取对一个方法的返回值了 */ Class<?> clazz = Class.forName("com.blog.annotation.test.User");//获取Class MyAnnotation classMyAnnotation = clazz.getDeclaredAnnotation(MyAnnotation.class);//获取类上的注解 System.out.println(classMyAnnotation.value());//直接调用注解里的方法获取值 System.out.println(classMyAnnotation.name()); Field userNameField = clazz.getDeclaredField("userName"); MyAnnotation fieldMyAnnotation = userNameField.getDeclaredAnnotation(MyAnnotation.class);//获取field的上的注解 System.out.println(fieldMyAnnotation.value()); System.out.println(fieldMyAnnotation.name()); Method test = clazz.getDeclaredMethod("test", null); MyAnnotation methodMyAnnotation = test.getAnnotation(MyAnnotation.class);//获取方法上的注解 System.out.println(methodMyAnnotation.value()); System.out.println(methodMyAnnotation.name()); }

    利用注解自己实现一个简单的spring框架,实现IOC和DI

    (即类由代理创建,属性由代理注入)  

    //1.自定义注解类 @Target({ElementType.CONSTRUCTOR}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface MyAnnotation { String[] value(); } //2.使用注解的类 import java.util.Date; public class User { private String userName; private String password; private String age; private User2 user2; private Date myDate; private Character character; @MyAnnotation({"张三三", "admin", "14", "李四四", "20190526", "2"}) public User() { } get和set...... } //3.实现IOC和DI的核心类 public class MySpring { public Object getBeanByClassName(String name, String dateFormat) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, ParseException { Class<?> clazz = Class.forName(name);//获取class Object obj = clazz.newInstance();//创建对象 Constructor<?> cons = clazz.getDeclaredConstructor();//根据class获取构造方法 MyAnnotation myAnnotation = cons.getDeclaredAnnotation(MyAnnotation.class);//获取构造方法上的注解 String[] values = myAnnotation.value();//获取注解里面的值 Field[] fields = clazz.getDeclaredFields();//获取fields //给创建的对象属性赋值 for (int i = 0; i < fields.length; i++) { fields[i].setAccessible(true); Class<?> type = fields[i].getType(); if (Date.class.isAssignableFrom(type)) {//日期类型 SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); fields[i].set(obj, sdf.parse(values[i])); } else if (Character.class.isAssignableFrom(type)) {//Character类型 char[] chars = values[i].toCharArray(); fields[i].set(obj, chars[0]); } else {//八大包装类型)或者类对象(此对象必须有一个String类型参数的构造方法的类对象) fields[i].set(obj, fields[i].getType().getDeclaredConstructor(String.class).newInstance(values[i])); } } return obj; } } //4.测试类 public class TestAnnotation { @Test public void test() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ParseException { MySpring mySpring = new MySpring(); User user = (User) mySpring.getBeanByClassName("com.blog.annotation.test.User", "yyyyMMdd"); System.out.println(user); } } //5.运行结果 { "age":"14", "character":"2", "myDate":1558800000000, "password":"admin", "user2":{ "name":"李四四" }, "userName":"张三三" }

     

    运行结果:

     

     

     

    最新回复(0)